### Eclipse Workspace Patch 1.0
#P contrib-738
Index: theme/wood/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/wood/header.html,v
retrieving revision 1.9.2.1
diff -u -r1.9.2.1 header.html
--- theme/wood/header.html	23 Nov 2007 16:41:14 -0000	1.9.2.1
+++ theme/wood/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/cornflower/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/cornflower/header.html,v
retrieving revision 1.16.2.2
diff -u -r1.16.2.2 header.html
--- theme/cornflower/header.html	20 Dec 2007 17:31:18 -0000	1.16.2.2
+++ theme/cornflower/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww.'/'.current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
-<body <?php
+<body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 <div class="cornflowersurround">
 <div id="page">
Index: theme/custom_corners/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/custom_corners/header.html,v
retrieving revision 1.10.2.13
diff -u -r1.10.2.13 header.html
--- theme/custom_corners/header.html	27 Feb 2008 10:31:30 -0000	1.10.2.13
+++ theme/custom_corners/header.html	7 Oct 2008 21:04:26 -0000
@@ -32,13 +32,22 @@
         //replace classlist with new one
         $bodytags = str_replace($classes[0], 'class="'.implode(' ', $classlist).'"', $bodytags);
     ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    };
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
     <?php if(!empty($infooutput)) { ?>
Index: theme/standard/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standard/header.html,v
retrieving revision 1.39.2.1
diff -u -r1.39.2.1 header.html
--- theme/standard/header.html	23 Nov 2007 16:41:14 -0000	1.39.2.1
+++ theme/standard/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/orangewhite/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/orangewhite/header.html,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 header.html
--- theme/orangewhite/header.html	23 Nov 2007 16:41:18 -0000	1.12.2.1
+++ theme/orangewhite/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    };
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/standardgreen/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standardgreen/header.html,v
retrieving revision 1.23.2.1
diff -u -r1.23.2.1 header.html
--- theme/standardgreen/header.html	23 Nov 2007 16:41:15 -0000	1.23.2.1
+++ theme/standardgreen/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/orangewhitepda/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/orangewhitepda/header.html,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 header.html
--- theme/orangewhitepda/header.html	23 Nov 2007 16:41:17 -0000	1.12.2.1
+++ theme/orangewhitepda/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    };
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/standardwhite/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standardwhite/header.html,v
retrieving revision 1.16.2.2
diff -u -r1.16.2.2 header.html
--- theme/standardwhite/header.html	23 Nov 2007 20:23:44 -0000	1.16.2.2
+++ theme/standardwhite/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/standardblue/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standardblue/header.html,v
retrieving revision 1.24.2.1
diff -u -r1.24.2.1 header.html
--- theme/standardblue/header.html	23 Nov 2007 16:41:16 -0000	1.24.2.1
+++ theme/standardblue/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/oceanblue/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/oceanblue/header.html,v
retrieving revision 1.19.2.1
diff -u -r1.19.2.1 header.html
--- theme/oceanblue/header.html	23 Nov 2007 16:41:14 -0000	1.19.2.1
+++ theme/oceanblue/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: grade/report/index.php
===================================================================
RCS file: /cvsroot/moodle/moodle/grade/report/index.php,v
retrieving revision 1.3.2.1
diff -u -r1.3.2.1 index.php
--- grade/report/index.php	17 Dec 2007 14:11:52 -0000	1.3.2.1
+++ grade/report/index.php	7 Oct 2008 21:04:25 -0000
@@ -61,8 +61,8 @@
 }
 
 if (empty($last)) {
-    if (in_array('grader', $reports)) {
-        $last = 'grader';
+    if (in_array('simple_grader', $reports)) { //LSU gradebook
+        $last = 'simple_grader'; //LSU gradebook
 
     } else if (in_array('user', $reports)) {
         $last = 'user';
Index: theme/formal_white/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/formal_white/header.html,v
retrieving revision 1.18.2.1
diff -u -r1.18.2.1 header.html
--- theme/formal_white/header.html	23 Nov 2007 16:41:14 -0000	1.18.2.1
+++ theme/formal_white/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/chameleon/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/chameleon/header.html,v
retrieving revision 1.9.2.1
diff -u -r1.9.2.1 header.html
--- theme/chameleon/header.html	11 Nov 2007 09:29:51 -0000	1.9.2.1
+++ theme/chameleon/header.html	7 Oct 2008 21:04:26 -0000
@@ -8,13 +8,22 @@
 
     <?php include('ui/chameleon.php'); ?>
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    };
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/metal/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/metal/header.html,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 header.html
--- theme/metal/header.html	23 Nov 2007 16:41:19 -0000	1.12.2.1
+++ theme/metal/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: theme/standardred/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standardred/header.html,v
retrieving revision 1.23.2.1
diff -u -r1.23.2.1 header.html
--- theme/standardred/header.html	23 Nov 2007 16:41:13 -0000	1.23.2.1
+++ theme/standardred/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: grade/import/lib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/grade/import/lib.php,v
retrieving revision 1.13.2.2
diff -u -r1.13.2.2 lib.php
--- grade/import/lib.php	7 Mar 2008 17:30:52 -0000	1.13.2.2
+++ grade/import/lib.php	7 Oct 2008 21:04:25 -0000
@@ -53,6 +53,15 @@
 function grade_import_commit($courseid, $importcode, $importfeedback=true, $verbose=true) {
     global $CFG, $USER;
 
+    //LSU gradebook - begin check for simple_gradelib
+    $use_function = false;
+    $file = $CFG->dirroot . '/grade/report/simple_grader/lib/simple_gradelib.php';
+    if (file_exists($file)) { 
+        require_once($file);
+        $use_function = true;
+    }
+    //LSU gradebook - end check for simple_gradelib
+
     $commitstart = time(); // start time in case we need to roll back
     $newitemids = array(); // array to hold new grade_item ids from grade_import_newitem table, mapping array
 
@@ -77,12 +86,19 @@
                 $instances[] = $gradeitem;
 
                 // insert each individual grade to this new grade item
+                // LSU gradebook - begin simple update final grade check
                 foreach ($grades as $grade) {
-                    if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
+                    if ($use_function) {
+                        if (!simple_update_final_grade($grade->userid, $gradeitem, 2, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
+                            $failed = true;
+                            break 2;
+                        }
+                    } else if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
                         $failed = true;
                         break 2;
                     }
                 }
+                // LSU gradebook - end simple update final grade check
             }
         }
 
@@ -118,10 +134,17 @@
                     if (!$importfeedback) {
                         $grade->feedback = false; // ignore it
                     }
-                    if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback)) {
+                // LSU gradebook - begin simple update final grade check
+                    if ($use_function){
+                        if(!simple_update_final_grade($grade->userid, $gradeitem, 2, $grade->finalgrade, 'import', $grade->feedback)) {
+                            $failed = true;
+                            break 2;
+                        }
+                    } else if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback)) {
                         $failed = 1;
                         break 2;
                     }
+                    // LSU gradebook - end simple update final grade check                    
                 }
                 //$itemdetails -> idnumber = $gradeitem->idnumber;
                 $modifieditems[] = $itemid;
Index: theme/standardlogo/header.html
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standardlogo/header.html,v
retrieving revision 1.26.2.2
diff -u -r1.26.2.2 header.html
--- theme/standardlogo/header.html	10 Jul 2008 09:48:49 -0000	1.26.2.2
+++ theme/standardlogo/header.html	7 Oct 2008 21:04:26 -0000
@@ -6,13 +6,22 @@
     <title><?php echo $title ?></title>
     <link rel="shortcut icon" href="<?php echo $CFG->themewww .'/'. current_theme() ?>/favicon.ico" />
     <?php include("$CFG->javascript"); ?>
+    <?php //LSU gradebook - start menu fix
+    $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } 
+    //LSU gradebook - end menu fix 
+    ?>
+    
 </head>
 
 <body<?php
     echo " $bodytags";
     if ($focus) {
         echo " onload=\"setfocus()\"";
-    }
+    } //LSU gradebook - Start check 
+    else {
+    echo " onload=\"replace_plugin()\"";
+    } //LSU gradebook - End check
     ?>>
 
 <div id="page">
Index: lib/gradelib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/gradelib.php,v
retrieving revision 1.120.2.26
diff -u -r1.120.2.26 gradelib.php
--- lib/gradelib.php	13 May 2008 21:51:47 -0000	1.120.2.26
+++ lib/gradelib.php	7 Oct 2008 21:04:25 -0000
@@ -835,6 +835,15 @@
  */
 function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) {
 
+// LSU gradebook - Check for Simple Grader Report 
+        global $CFG;
+             
+        $exists = file_exists($CFG->dirroot. '/grade/report/simple_grader/lib/simple_gradelib.php');
+        if ($exists) {
+             require_once($CFG->dirroot . '/grade/report/simple_grader/lib/simple_gradelib.php');
+             return simple_grade_regrade_final_grades($courseid, $userid, $updated_item);
+        }   
+// LSU gradebook - End check for Simple Grader Report
     $course_item = grade_item::fetch_course_item($courseid);
 
     if ($userid) {
Index: lib/grade/grade_item.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/grade/grade_item.php,v
retrieving revision 1.130.2.26
diff -u -r1.130.2.26 grade_item.php
--- lib/grade/grade_item.php	27 Mar 2008 17:13:01 -0000	1.130.2.26
+++ lib/grade/grade_item.php	7 Oct 2008 21:04:26 -0000
@@ -194,7 +194,7 @@
      * Aggregation coeficient used for weighted averages
      * @var float $aggregationcoef
      */
-    var $aggregationcoef = 0;
+    var $aggregationcoef = 1; //LSU gradebook
 
     /**
      * Sorting order of the columns.
Index: grade/report/projected/styles.php
===================================================================
RCS file: grade/report/projected/styles.php
diff -N grade/report/projected/styles.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/styles.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,49 @@
+#error {
+  color: #FF0000;
+}
+
+.grade-report-user table#user-grade .datesubmitted {
+  font-size: 0.7em;
+}
+
+.grade-report-user table#user-grade .courseitem,
+.grade-report-user table#user-grade .categoryitem {
+  font-weight: bold;
+}
+
+
+.grade-report-projected td {
+  height: 25px;
+}
+
+.grade-report-projected .categoryitem {
+display: block;
+padding-top: 10px;
+padding-bottom: 10px;
+background-color: #eee;
+height: 24px;
+}
+
+.grade-report-projected .invisitext {
+display: none;
+}
+
+
+.grade-report-projected .courseitem {
+display: block;
+padding-top: 15px;
+padding-bottom: 15px;
+background-color: #ddd;
+color: #333;
+height: 24px;
+}
+
+.grade-report-projected span {
+padding: 5px;
+}
+
+/* this must be last if we want to override other category and course item colors */
+.grade-report-user table#user-grade .hidden,
+.grade-report-user table#user-grade .hidden a {
+  color:#aaaaaa;
+}
Index: blocks/anonymous_grade/lang/en_utf8/block_anonymous_grade.php
===================================================================
RCS file: blocks/anonymous_grade/lang/en_utf8/block_anonymous_grade.php
diff -N blocks/anonymous_grade/lang/en_utf8/block_anonymous_grade.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/lang/en_utf8/block_anonymous_grade.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,10 @@
+<?php
+
+$string['blockname'] = "Grade Features";
+$string['extra_features'] = 'Enable Extra Grade Features ';
+$string['anonymous_field'] = 'Anonymous Profile Field: ';
+$string['extra_credit'] = 'Extra Credit for Weighted Mean and Simple Weighted Mean';
+$string['limit_adjust'] = 'Limit adjust value: +/-';
+$string['limit_category'] = 'Limit anonymous grading to: ';
+
+?>
Index: grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregateonlygraded.html
===================================================================
RCS file: grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregateonlygraded.html
diff -N grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregateonlygraded.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregateonlygraded.html	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,2 @@
+<h1>Count Empty Grades as Zeroes</h1>
+<p>Nonexistent grades are either treated as minimal grades (0 unless specified) or not included in aggregation.</p>
Index: grade/import/mymathlab/README
===================================================================
RCS file: grade/import/mymathlab/README
diff -N grade/import/mymathlab/README
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/README	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,1 @@
+Copy gradeimport_mymathlab.php to /lang/en_utf8/
Index: grade/import/mymathlab/version.php
===================================================================
RCS file: grade/import/mymathlab/version.php
diff -N grade/import/mymathlab/version.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/version.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,6 @@
+<?php
+
+$plugin->version  = 2008090900;
+$plugin->requires = 2007101000;
+
+?>
Index: grade/report/simple_grader/quick_edit_table.php
===================================================================
RCS file: grade/report/simple_grader/quick_edit_table.php
diff -N grade/report/simple_grader/quick_edit_table.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/quick_edit_table.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,539 @@
+<?php // $Id: quick_edit_table.php,v 1.0 2008-05-14 17:03:46 pcali1 Exp $
+
+require_once ('lib/simple_grade_hook.php');
+
+/**
+ * Author: Philip Cali
+ * Date: 05/01/2008
+ *
+ * Abstract quick edit table, who generates the html for the quick edit screens
+ */
+abstract class quick_edit_table {
+    // depending on the mode the teacher is coming from, items can be either grades or students
+    // items, in the quick edit sense, editable items
+    var $data;
+
+    // The mode; that is, where they're coming from
+    var $mode;
+    
+    // The course tied to this quick edit table
+    var $courseid;
+
+    // If anonymous is enabled, the field id
+    var $fieldid;
+
+    var $scale_list;
+
+    function quick_edit_table($id, $mode, $fieldid=0) {
+        $this->courseid = $id;
+        $this->mode = $mode;
+        $this->fieldid = $fieldid;
+        $this->scale_list = Array();
+    }
+
+    function setData($data) {
+        $this->data = $data;
+    }
+
+    public function getScale($itemid) {
+        if (isset($this->scale_list[$itemid])) {
+            return $this->scale_list[$itemid];
+        }
+        return null;
+    }
+
+    public function setScale($item) {
+        if (isset($this->scale_list[$item->id]) || $item->scaleid == null) {
+            return;
+        }
+        $scale = get_field('scale', 'scale', 'id', $item->scaleid);
+        // Reorganize values
+        $instance = Array();
+        $i = 0;
+        foreach ( explode(',',$scale) as $opt) {
+            $i++;
+            $instance[$i] = $opt;
+        }
+        $this->scale_list[$item->id] = $instance;
+    }
+
+    /**
+     * Delegates the format functionality to the table in question
+     */
+    public abstract function formatItemName($item);
+    
+    /**
+     * Children tables will call the parents getGradeInputs method
+     */
+    public abstract function getSpecialGradeInputs($item, $tabindex, $numitems);
+
+    public abstract function customJavascript();
+
+    /**
+     * Common headers between tables
+     */ 
+    function getGradeHeaders() {
+        $tableHeaders = '<th class="header Range" scope="col">'.get_string('range', 'grades').' </th>';
+        $tableHeaders .= '<th class="header finalgrade" scope="col">'.get_string('grade').'</th>';
+        $tableHeaders .= '<th class="header feedback" scope="col">'.get_string('feedback').'</th>';
+        return $tableHeaders;
+    }
+
+    /**
+     * Common elements, some of the time (overrides and excludes);  Sums can't be excluded,
+     * Manual items can't be overriden
+     */
+    function getTableHeaders($showexcludes=true) {
+        $tableHeaders = $this->getGradeHeaders();
+
+        if ($this->data['interest']->itemtype != 'manual') {
+            $tableHeaders .= '<th class="header override" scope="col">'. get_string('override', 'gradereport_simple_grader'). 
+                         '<span class="inclusion-links"> <a onclick="toggleCheckboxes(\'override\', true)" '.
+                         'href="javascript:void(0);">'.get_string('all').'</a>/<a onclick="toggleCheckboxes(\'override\', false)" 
+                          href="javascript:void(0);">'.get_string('none').'</a></span></th>';
+        }
+        if ($showexcludes) {
+            $tableHeaders .= '<th class="header exclude" scope="col">'. 
+                get_string('exclude', 'gradereport_simple_grader'). 
+        '<span class="inclusion-links"> <a onclick="toggleCheckboxes(\'exclude\', true)" '.
+                'href="javascript:void(0);">'.get_string('all') .
+                '</a>/<a onclick="toggleCheckboxes(\'exclude\', false)" '.
+                'href="javascript:void(0);">'. get_string('none'). '</a></span></th>';
+        }
+
+        return $tableHeaders;
+    }
+
+    /**
+     * Method that prints out the rang html
+     */
+    function getRangeHtml($grade_item) {
+        $gradebox = '<td class="cell range">';
+        $gradebox .= format_float($grade_item->grademin, 2) . ' &ndash; '. format_float($grade_item->grademax, 2);
+        $gradebox .= '</td>';
+        return $gradebox;
+    }
+
+    /**
+     * Method that prints out the feedback html
+     */
+    function getFeedBackHtml($htmlnames, $tabindex, $grade, $disabled = '') {
+        $feedback = (empty($grade->feedback)) ? '': $grade->feedback;
+
+        $gradebox = '<td class="cell feedback">';
+        $gradebox .= '<input id="feedback_'.$htmlnames.'" type="text" name="feedback_'.$htmlnames.'" value="'.
+                    $feedback. '" '.$disabled.' tabindex='. $tabindex .'/>';
+        $gradebox .= '<input type="hidden" name="oldfeedback_'.$htmlnames.'" value="'. $feedback.'"/>';
+        $gradebox .= "</td>";
+        return $gradebox;
+    }  
+  
+    /**
+     * Method that prints out the finalgrade html
+     */
+    function getFinalGradeHtml($itemid, $htmlnames, $oldgrade, $tabindex, $disabled='', $completed = false) {
+        $use_scale = false;
+        if ($scale = $this->getScale($itemid)) {
+            $use_scale = true;
+        } 
+
+        $gradebox = '<td class="cell finalgrade">';
+        if ($completed){
+            $gradebox .= $oldgrade;
+        } else if ($use_scale) {
+            $nogradestr = get_string('nograde');
+            $gradebox .= choose_from_menu($scale, 'grade_'.$htmlnames, $oldgrade, $nogradestr, '', '-1', true, ($disabled) ? true : false, 0, 'grade_'.$htmlnames);
+        } else {
+            $gradebox .= '<input id="grade_'.$htmlnames.'" type="text" name="grade_'.$htmlnames.'" value="'.
+                    $oldgrade. '"  '.$disabled.' tabindex='.$tabindex.'/>';
+            $gradebox .= '<input type="hidden" name="oldgrade_'.$htmlnames.'" value="'.$oldgrade.'"/>';
+        }
+        $gradebox .= "</td>";
+        return $gradebox;
+    }
+
+    /**
+     * Method that prints out the adjusted html
+     */
+    function getAdjustHtml($adjusted, $htmlnames, &$oldgrade) {
+        $adjusthtml = '<td class="cell anonymous"> <select name="adjustgrade_'. $htmlnames . '">';
+        $positive_selection = '';
+        $negative_selection = '';
+        if (isset($adjusted->adjust_value) && $adjusted->adjust_value >= 0) {
+            $positive_selection = 'selected="selected" ';
+        } else if (isset($adjusted->adjust_value) && $adjusted->adjust_value < 0) {
+            $negative_selection = 'selected"selected" ';
+        }
+        $adjusthtml .= '<option value="+" '. $positive_selection . '>+</option>';
+        $adjusthtml .= '<option value="-" '. $negative_selection . '>-</option>';
+        $oldvalue = (isset($adjusted->adjust_value)) ? format_float($adjusted->adjust_value, 2) : '';
+        $value = (!empty($oldvalue)) ? abs($oldvalue) : '';
+        $adjusthtml .= '</select><input type="text" name="adjustvalue_'. $htmlnames
+            . '" value="'. $value .'" size="4"/>';
+        $adjusthtml .= '<input type="hidden" name="oldadjustvalue_'.$htmlnames.'" value="'.$oldvalue.'"/></td>';
+        
+        $oldgrade = (isset($adjusted->grade_before)) ? format_float($adjusted->grade_before, 2) : $oldgrade;
+        return $adjusthtml;
+    }
+
+    /**
+     * Prints out the 'action' checkboxes (excludes and overrides)
+     */
+    function getCheckboxHtml($checked, $disabled, $value, $htmlnames, $action="exclude", $onclick="") {
+         $gradebox = '<td class="cell '.$action.'">';
+         $gradebox .= '<input type="hidden" name="old'.$action.'_'.$htmlnames.'" value="'. $value .'"/>';
+         $gradebox .= '<input type="hidden" name="'.$action.'_'.$htmlnames.'" value="0"/>';
+         $gradebox .= '<input id="'.$action.'_'.$htmlnames.'" type="checkbox" name="'.$action.'_'.$htmlnames.'" '. 
+                  $checked. $disabled. $onclick . ' value="1"/>';
+         $gradebox .= "</td>";
+         return $gradebox;
+    }
+
+    /**
+     * Method that prints out the grade inputs
+     */
+    function getGradeInputs($userid, $grade_item, $tabindex, $numitems, $showoverrides=true, $table='grade_grades', $showexcludes=true, $showanonymous=false) {
+
+        $this->setScale($grade_item);
+
+        $htmlnames = $userid . '_'. $grade_item->id;
+        
+        if (!$grade = get_record($table, 'itemid', $grade_item->id, 'userid', $userid)){
+            $grade = new grade_grade(array('itemid'=> $grade_item->id, 'userid'=>$userid));
+        }
+
+        // changed for multiplicator
+        $finalgrade = ($grade_item->itemtype == 'manual') ? $grade->rawgrade : $grade->finalgrade;
+        //end change
+
+        $oldgrade =  (empty($finalgrade)) ? '' : format_float($finalgrade, 2);
+        $exclude = $grade->excluded > 0 ? 1 : 0;
+        $overridden = $grade->overridden > 0 ? 1 : 0;
+        $completed = (isset($grade_item->completed)) ? $grade_item->completed : false;
+        
+        if (!$overridden and $grade_item->itemtype != 'manual' and $showoverrides){
+            $disabled = 'disabled="disabled"';
+        } else {
+            $disabled = '';
+        }
+        
+       
+        //Get the adjusted record for this anonymous grade 
+        if ($showanonymous || $completed) {
+            $adjusted = get_record('block_anon_grade_adjustments', 'userid', $userid, 'itemid', $grade_item->id);
+            $adjusthtml = $this->getAdjustHtml($adjusted, $htmlnames, $oldgrade);
+        } else {
+            $adjusthtml = '';
+        }
+
+        //Get range
+        $gradebox = $this->getRangeHtml($grade_item);
+        
+        //Get the final grade input
+        $gradebox .= $this->getFinalGradeHtml($grade_item->id, $htmlnames, $oldgrade, $tabindex, $disabled, $completed);
+        
+        //Get the feeback input
+        $gradebox .= $this->getFeedBackHtml($htmlnames, $tabindex + $numitems, $grade, $disabled);
+
+        //Get the checkboxes
+        if ($showoverrides ) {
+            $checked = ($grade->overridden) ? 'checked="checked"' : '';
+            $disable = ($grade_item->itemtype == 'manual') ? 'disabled="disabled"' : '';
+            $gradebox .= $this->getCheckboxHtml($checked, $disable, $overridden, $htmlnames, "override", 
+                'onclick="toggleEdit(\''.$userid.'\', \''.$grade_item->id.'\');"'); 
+        }
+
+        if ($showexcludes) {
+            $checked = ($grade->excluded) ? 'checked="checked"' : '';
+            $disable = ($grade_item->aggregation == GRADE_AGGREGATE_SUM) ? 'disabled="disabled"' : '';
+            $gradebox .= $this->getCheckboxHtml($checked, $disable, $exclude, $htmlnames); 
+        }
+
+        //Adding the adjusted html
+        $gradebox .= $adjusthtml;
+
+        return $gradebox;             
+        
+    }
+
+    /**
+     * The entry function to display the table
+     */ 
+    function display() {
+        global $CFG;
+
+        $displayhtml = '<h1 class="quick_edit_header">'.$this->data['header'].'</h1>';
+        $displayhtml .= '<form name="quick_edit_form" method="post" action="quick_edit.php">'; 
+        $displayhtml .= '<table id="quick_edit" class="flexible submissions">';
+        $displayhtml .= $this->getTableHeaders();
+
+        $rowcount = 0;
+        $tabindex = 1;
+        $numitems = count($this->data['items']);
+        foreach ($this->data['items'] as $item) {
+            $displayhtml .= '<tr class="r'.$rowcount.'">';
+            $displayhtml .= $this->formatItemName($item);
+
+            $displayhtml .= $this->getSpecialGradeInputs($item, $tabindex, $numitems);
+            $displayhtml .= "</tr>";
+
+            $rowcount = ($rowcount == 0) ? 1 : 0;
+            $tabindex += 1;
+        }
+        
+        $displayhtml .= "</table>";
+        $displayhtml .= $this->getHiddenInputs();
+        $displayhtml .=  '<input class="center" type="submit" value="'.get_string('update').'" /></form>';
+        $displayhtml .= $this->customJavascript();
+        echo $displayhtml;
+    }
+
+    function getHiddenInputs() {
+        $hiddeninputs = '<input type="hidden" name="id" value="'.$this->courseid.'"/>';
+        $hiddeninputs .= '<input type="hidden" name="mode" value="'.$this->mode.'"/>';
+        $hiddeninputs .= '<input type="hidden" name="itemid" value="'.$this->data['interest']->id .'"/>';
+        if ($this->fieldid) {
+            $hiddeninputs .= '<input type="hidden" name="fieldid" value="'.$this->fieldid .'"/>';    
+        }
+        return $hiddeninputs;
+    }
+
+}
+
+
+/**
+ * User table is the quick edit table represented when the teacher 
+ * clicks on the QE link for a student
+ */
+class quick_edit_user_table extends quick_edit_table {
+
+    function quick_edit_user_table($id, $mode) {
+        parent::quick_edit_table($id, $mode);
+    }
+    
+    public function formatItemName ($item) {
+        $itemcells = '<td class="cell fullname">';
+        $itemcells .= get_element_icon($item) . '<a href="quick_edit.php?id=' . $this->courseid . '&amp;mode=grades&amp;itemid='.$item->id.'">'.
+                         $item->itemname.'</a></td>';
+        $itemname = ($item->fullname == '?') ? get_field('course', 'fullname', 'id', $this->courseid) : $item->fullname;
+        $itemcells .= '<td class="cell grade_category">'. $itemname . '</td>';
+        $itemcells .= "</td>";
+        return $itemcells;
+    }
+
+    public function getSpecialGradeInputs($item, $tabindex, $numitems) {
+        $grade_item = $item;
+        $userid = $this->data['interest']->id;
+        return $this->getGradeInputs($userid, $grade_item, $tabindex, $numitems);
+    }
+
+    function getTableHeaders() {
+        $tableHeaders = "<tr>";
+        $tableHeaders .= '<th class="header fullname" scope="col">'.get_string('assessment_name', 'gradereport_simple_grader').' </th>';
+        $tableHeaders .= '<th class="header grade_category" scope="col">'.get_string('grade_category', 'gradereport_simple_grader').'</th>';
+        $tableHeaders .= parent::getTableHeaders();
+        $tableHeaders .= "</tr>";
+        return $tableHeaders;
+    }
+
+    function customJavascript() {
+        return '';
+    }
+}
+
+/**
+ * Anonymous tables are used for anonymous grading, which can ONLY be done through this screen
+ */
+class quick_edit_anonymous_table extends quick_edit_table {
+
+    function quick_edit_anonymous_table($id, $mode, $fieldid){
+        parent::quick_edit_table($id, $mode, $fieldid);
+    }
+
+    public function formatItemName ($item) {
+        $itemcells = '<td class="cell anonymous">';
+        $itemcells .= (!$item->data) ? get_string('anonymous', 'gradereport_simple_grader') : $item->data;
+        $itemcells .= '</td>';
+        return $itemcells;
+    } 
+    
+    public function getSpecialGradeInputs($item, $tabindex, $numitems) {
+        $grade_item = $this->data['interest'];
+        $userid = $item->id;
+
+        return $this->getGradeInputs($userid, $grade_item, $tabindex, $numitems, false, 'block_anon_grade_grades', false, true);
+    }
+
+    function getTableHeaders() {
+        $tableHeaders = '<tr>';
+        $tableHeaders .= '<th class="header anonymous" scope="col">'.
+                    get_string('anonymous', 'gradereport_simple_grader').'</th>';
+        $tableHeaders .= parent::getGradeHeaders();
+        $tableHeaders .= '<th class="header adjustment" scope="col">'.
+                    get_string('adjustments', 'gradereport_simple_grader').'</th>';
+        $tableHeaders .= '</tr>';
+        return $tableHeaders;
+    }
+
+    function customJavascript() {
+        return '';
+    }
+}
+
+/**
+ * Table for any grade item. Displays all the students
+ */
+class quick_edit_grade_table extends quick_edit_table {
+
+    function quick_edit_grade_table($id, $mode) {
+        parent::quick_edit_table($id, $mode);
+    }
+
+    public function formatItemName ($item) {
+
+        $imagelink = custom_user_image($item);
+        $itemcells = '<td class="cell picture">';
+        $itemcells .= $imagelink . "</td>";
+        $itemcells .= '<td class="cell fullname">';
+        $itemcells .= '<a href="quick_edit.php?id='. $this->courseid. '&amp;mode=user&amp;itemid='. $item->id .'">'.
+                      fullname($item).'</a>';
+        $itemcells .= "</td>";
+        return $itemcells;
+    }
+
+    public function getSpecialGradeInputs($item, $tabindex, $numitems) {
+        $grade_item = $this->data['interest'];
+        $userid = $item->id;
+
+        return $this->getGradeInputs($userid, $grade_item, $tabindex, $numitems, 
+                        ($grade_item->itemtype == 'manual') ? false : true,
+                        'grade_grades',
+                        ($grade_item->aggregation == GRADE_AGGREGATE_SUM) ? false : true);
+    }
+
+    function getTableHeaders() {
+        $tableHeaders = "<tr>";
+        $tableHeaders .= '<th class="header picture" scope="col"></th>';
+        $tableHeaders .= '<th class="header fullname" scope="col">'.get_string('firstname').' / '.get_string('lastname').'</th>';
+        
+        if ($this->data['interest']->aggregation == GRADE_AGGREGATE_SUM){
+            $tableHeaders .= parent::getTableHeaders(false);
+        } else {
+            $tableHeaders .= parent::getTableHeaders();
+        }
+        if ($this->data['interest']->completed) {
+        $tableHeaders .= '<th class="header adjustment" scope="col">'.
+                    get_string('adjustments', 'gradereport_simple_grader').'</th>';
+        }
+        $tableHeaders .= "</tr>";
+        return $tableHeaders; 
+    }
+ 
+    function customJavascript() {
+        return '';
+    }
+}
+
+class quick_edit_course_table extends quick_edit_table {
+
+    private $categoryCache;
+
+    public function findCourseCategories() {
+        if ($this->categoryCache) {
+            return $this->categoryCache;
+        }
+        
+        $gradecategories = get_records("grade_categories", 'courseid', $this->courseid);
+    
+        foreach ($gradecategories as $category) {
+            if ($category->fullname == "?") {
+                $category->fullname = $this->data['interest']->fullname;
+            }
+            $this->categoryCache[$category->id] = $category->fullname;
+        }
+
+        return $this->categoryCache; 
+    }
+
+    function quick_edit_course_table($id, $mode) {
+        parent::quick_edit_table($id, $mode);
+    }
+
+    public function formatItemName($item) {
+        global $CFG;
+
+        $base_url = $CFG->wwwroot . '/grade/edit/simple_tree/item.php?courseid=';
+        $itemcells = '<td class="cell fullname">';
+        $itemcells .= get_element_icon($item) . '<a href="'.$base_url . $this->courseid . '&amp;id='.$item->id.'">'.
+                          $item->itemname.'</a></td>';
+        $itemcells .= '<td class="cell grade_category">';
+        $itemcells .= choose_from_menu($this->findCourseCategories(), $item->id . '_selector',
+                    $item->categoryid, '', 'toggleDropItemid(\''.$item->id.'\')', '0', true);
+        $itemcells .= "</td>";
+
+        return $itemcells;    
+    }
+
+    public function getSpecialGradeInputs($item, $tabindex, $numitems) {
+        $course = $this->data['interest'];
+        $grade_item = $item;
+
+        $disabled_cat = $grade_item->aggregation == GRADE_AGGREGATE_SUM || $grade_item->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2;
+
+        $agg_value = $grade_item->aggregationcoef;
+        $checked = ($agg_value == 0) ? 'checked="checked"' : "";
+        $disabled = ($agg_value == 0 || $disabled_cat) ? 'disabled="disabled"' : "";
+        $max_grade = format_float($grade_item->grademax, 2);
+        $curve_to = format_float($grade_item->grademax * $grade_item->multfactor, 2);
+
+        $agg = $grade_item->id . '_item_weight';
+        $xc = $grade_item->id . '_extra_credit';
+
+        $html = '<td class="cell max_value"><input name="'.
+            $grade_item->id.'_max_value" value="'.$max_grade.'" size="6"/></td>';
+        $html .= '<td class="cell curve_to"><input name="'.
+            $grade_item->id.'_curve_to" value="'.$curve_to.'" size="6"/></td>';
+        $html .= '<td class="cell item_weight"><input id="'.$agg.'" name="'.
+            $agg.'" value="'.$agg_value.'" '.$disabled.' /></td>';
+        $html .= '<td class="cell extra_credit"><input id="'.$xc.'" type="checkbox" name="'.
+            $xc.'" '.$checked.'" onclick="toggleAggCoef(\''
+            .$item->id.'\');"/></td>';
+
+        return $html;
+    }
+
+    function getTableHeaders() {
+        $tableHeaders = "<tr>";
+        $tableHeaders .= '<th class="header fullname" scope="col">'.get_string('assessment_name', 'gradereport_simple_grader').' </th>';
+        $tableHeaders .= '<th class="header grade_category" scope="col">'.get_string('grade_category', 'gradereport_simple_grader').'</th>';
+        $tableHeaders .= '<th class="header max_value" scope="col">'.get_string('grademax', 'grades').' </th>';
+        $tableHeaders .= '<th class="header curve_to" scope="col">'.'Curve To'.' </th>';
+        $tableHeaders .= '<th class="header item_weight" scope="col">'.'Item Weight'.' </th>';
+        $tableHeaders .= '<th class="header extra_credit" scope="col">'.get_string('aggregationcoefextra', 'grades').' </th>';
+        $tableHeaders .= "</tr>";
+        return $tableHeaders;
+    }
+
+    function customJavascript() {
+        $html = "\n";
+        $html .= '<script type="text/javascript">';
+        $html .= "var sum_cats = Array();\n";
+        foreach ($this->data['items'] as $item) {
+            if ($item->aggregation == GRADE_AGGREGATE_SUM || $item->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) {    
+                $html .= "sum_cats.push({$item->categoryid});\n"; 
+            }
+        }
+        $html .= '</script>';
+        return $html;
+    }
+
+    function getHiddenInputs() {
+        global $CFG;
+        $html = parent::getHiddenInputs();
+        $html .= '<a class="create_item" href="'.$CFG->wwwroot.'/grade/edit/simple_tree/item.php?courseid='.$this->courseid.'">Add a new Grade Item</a><br/>';
+        $html .= '<a class="create_category" href="'.$CFG->wwwroot.'/grade/edit/simple_tree/category.php?courseid='.$this->courseid.'">Add a new Grade Category</a><br/>';
+        return $html;
+    }    
+}
+
+?>
Index: grade/report/simple_grader/lib/simple_gradelib.php
===================================================================
RCS file: grade/report/simple_grader/lib/simple_gradelib.php
diff -N grade/report/simple_grader/lib/simple_gradelib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lib/simple_gradelib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,768 @@
+<?php
+
+    
+/**
+ * Pulled from grade_item, for the grade book
+ */
+function simple_update_final_grade ($userid, $grade_item, $multiplier=1, $finalgrade=false, $source=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) {
+    global $USER, $CFG;
+
+    $result = true;
+
+    $grade = new grade_grade(array('itemid'=> $grade_item->id, 'userid'=>$userid));
+    $grade->grade_item = &$grade_item;
+    
+    if (empty($usermodified)) {
+        $grade->usermodified = $USER->id;
+    }
+    else {
+        $grade->usermodified = $usermodified;
+    }
+
+    
+    if ($grade->is_locked()) {
+         // do not update locked grades at all
+         return false;
+    }
+
+    $locktime = $grade->get_locktime();
+    if ($locktime and $locktime < time()) {
+         // do not update grades that should be already locked, force regrade instead
+         $grade_item->force_regrading();
+         return false;
+    }
+
+    // is the item manual?; must be treated differently
+    $conditional_logic = $grade_item->itemtype == 'manual';
+
+     $oldgrade = new object();
+     if ($conditional_logic) {
+        $oldgrade->finalgrade = $grade->rawgrade;
+        $oldgrade->rawgrademax = $grade_item->grademax;
+        $oldgrade->rawgrademin = $grade_item->grademin;
+     } else {
+        $oldgrade->finalgrade = $grade->finalgrade;
+     }
+     $oldgrade->overridden     = $grade->overridden;
+     $oldgrade->feedback       = $grade->feedback;
+     $oldgrade->feedbackformat = $grade->feedbackformat;
+
+     // changed grade?
+     if ($finalgrade !== false) {
+         if ($grade_item->is_overridable_item()) {
+             $grade->overridden = time();
+         } else {
+             $grade->overridden = 0;
+         }
+
+         if (is_null($finalgrade)) {
+             $real_finalgrade = null;
+         } else {
+             $real_finalgrade = bounded_number($grade_item->grademin, $finalgrade, $grade_item->grademax * $multiplier);   
+         }
+
+        if ($conditional_logic) {
+            $grade->rawgrade = $real_finalgrade;
+            $grade->rawgrademax = $grade_item->grademax;
+            $grade->rawgrademin = $grade_item->grademin;
+        } else {
+            $grade->finalgrade = $real_finalgrade;
+        }
+     }
+
+     // do we have comment from teacher?
+     if ($feedback !== false) {
+         if ($grade_item->is_overridable_item_feedback()) {
+             // external items (modules, plugins) may have own feedback
+             $grade->overridden = time();
+         }
+
+         $grade->feedback       = $feedback;
+         $grade->feedbackformat = $feedbackformat;
+     }
+
+     if (empty($grade->id)) {
+         $grade->timecreated  = null;   // hack alert - date submitted - no submission yet
+         $grade->timemodified = time(); // hack alert - date graded
+         $result = (boolean)$grade->insert($source);
+
+     } else if (grade_floats_different($real_finalgrade, $oldgrade->finalgrade)
+             or $grade->feedback       !== $oldgrade->feedback
+             or $grade->feedbackformat != $oldgrade->feedbackformat
+             or $grade->overridden     != $oldgrade->overridden) {
+         $grade->timemodified = time(); // hack alert - date graded
+         $result = $grade->update($source);
+     } else {
+            // no grade change
+            return $result;
+     }
+
+     if (!$result) {
+         // something went wrong - better force final grade recalculation
+         $grade_item->force_regrading();
+
+     } else if ($grade_item->is_course_item() and !$grade_item->needsupdate) {
+         if (simple_grade_regrade_final_grades($grade_item->courseid, $userid, $grade_item, $multiplier) !== true) {
+             $grade_item->force_regrading();
+         }
+
+     } else if (!$grade_item->needsupdate) {
+         $course_item = grade_item::fetch_course_item($grade_item->courseid);
+         if (!$course_item->needsupdate) {
+             if (simple_grade_regrade_final_grades($grade_item->courseid, $userid, $grade_item, $multiplier) !== true) {
+                 $grade_item->force_regrading();
+             }
+         } else {
+             $grade_item->force_regrading();
+         }
+     }
+
+     return $result;
+}
+
+/**
+ * Pulled from gradelib
+ */
+function simple_grade_regrade_final_grades($courseid, $userid=null, $updated_item=null, $multiplier=2) {
+
+    $course_item = grade_item::fetch_course_item($courseid);
+
+    if ($userid) {
+        // one raw grade updated for one user
+        if (empty($updated_item)) {
+            error("updated_item_id can not be null!");
+        }
+        if ($course_item->needsupdate) {
+            $updated_item->force_regrading();
+            return array($course_item->id =>'Can not do fast regrading after updating of raw grades');
+        }
+
+    } else {
+        if (!$course_item->needsupdate) {
+            // nothing to do :-)
+            return true;
+        }
+    }
+
+    $grade_items = grade_item::fetch_all(array('courseid'=>$courseid));
+    $depends_on = array();
+
+    // first mark all category and calculated items as needing regrading
+    // this is slower, but 100% accurate
+    foreach ($grade_items as $gid=>$gitem) {
+        if (!empty($updated_item) and $updated_item->id == $gid) {
+            $grade_items[$gid]->needsupdate = 1;
+
+        } else if ($gitem->is_course_item() or $gitem->is_category_item() or $gitem->is_calculated()) {
+            $grade_items[$gid]->needsupdate = 1;
+        }
+
+        // construct depends_on lookup array
+        $depends_on[$gid] = $grade_items[$gid]->depends_on();
+    }
+
+    $errors = array();
+    $finalids = array();
+    $gids     = array_keys($grade_items);
+    $failed = 0;
+
+    while (count($finalids) < count($gids)) { // work until all grades are final or error found
+        $count = 0;
+        foreach ($gids as $gid) {
+            if (in_array($gid, $finalids)) {
+                continue; // already final
+            }
+
+            if (!$grade_items[$gid]->needsupdate) {
+                $finalids[] = $gid; // we can make it final - does not need update
+                continue;
+            }
+
+            $doupdate = true;
+            foreach ($depends_on[$gid] as $did) {
+                if (!in_array($did, $finalids)) {
+                    $doupdate = false;
+                    continue; // this item depends on something that is not yet in finals array
+                }
+            }
+
+            //ok - let's update, calculate or aggregate :-)
+            if ($doupdate) {
+                //regrade; score needs over maximum
+                $result = simple_grade_item_regrade_grades($grade_items[$gid],$userid, $multiplier);
+
+                if ($result === true) {
+                    $grade_items[$gid]->regrading_finished();
+                    $grade_items[$gid]->check_locktime(); // do the locktime item locking
+                    $count++;
+                    $finalids[] = $gid;
+
+                } else {
+                    $grade_items[$gid]->force_regrading();
+                    $errors[$gid] = $result;
+                }
+            }
+        }
+
+        if ($count == 0) {
+            $failed++;
+        } else {
+            $failed = 0;
+        }
+
+        if ($failed > 1) {
+            foreach($gids as $gid) {
+                if (in_array($gid, $finalids)) {
+                    continue; // this one is ok
+                }
+                $grade_items[$gid]->force_regrading();
+                $errors[$grade_items[$gid]->id] = 'Probably circular reference or broken calculation formula'; // TODO: localize
+            }
+            break; // oki, found error
+        }
+    }
+
+    if (count($errors) == 0) {
+        if (empty($userid)) {
+            // do the locktime locking of grades, but only when doing full regrading
+            grade_grade::check_locktime_all($gids);
+        }
+        return true;
+    } else {
+        return $errors;
+    }
+
+}
+
+
+    /**
+     * Pulled from grade item
+     * Given a float grade value or integer grade scale, applies a number of adjustment based on
+     * grade_item variables and returns the result.
+     * @param float $rawgrade The raw grade value.
+     * @param float $rawmin original rawmin
+     * @param float $rawmax original rawmax
+     * @return mixed
+     */
+    function simple_adjust_raw_grade($grade_item, $rawgrade, $rawmin, $rawmax, $multiplier=2) {
+        if (is_null($rawgrade)) {
+            return null;
+        }
+
+        if ($grade_item->gradetype == GRADE_TYPE_VALUE) { // Dealing with numerical grade
+
+            if ($grade_item->grademax < $grade_item->grademin) {
+                return null;
+            }
+
+            if ($grade_item->grademax == $grade_item->grademin) {
+                return $grade_item->grademax; // no range
+            }
+
+            // Standardise score to the new grade range
+            // NOTE: this is not compatible with current assignment grading
+            if ($grade_item->itemmodule != 'assignment' and ($rawmin != $grade_item->grademin or $rawmax != $grade_item->grademax)) {
+                //$rawgrade = grade_grade::standardise_score($rawgrade, $rawmin, $rawmax, $grade_item->grademin, $grade_item->grademax);
+            }
+
+            // Apply other grade_item factors
+            $rawgrade *= $grade_item->multfactor;
+            $rawgrade += $grade_item->plusfactor;
+
+            return bounded_number($grade_item->grademin, $rawgrade, $grade_item->grademax*$multiplier);
+
+        } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) { // Dealing with a scale value
+            if (empty($grade_item->scale)) {
+                $grade_item->load_scale();
+            }
+
+            if ($grade_item->grademax < 0) {
+                return null; // scale not present - no grade
+            }
+
+            if ($grade_item->grademax == 0) {
+                return $grade_item->grademax; // only one option
+            }
+
+            // Convert scale if needed
+            // NOTE: this is not compatible with current assignment grading
+            /*if ($grade_item->itemmodule != 'assignment' and ($rawmin != $grade_item->grademin or $rawmax != $grade_item->grademax)) {
+                //$rawgrade = grade_grade::standardise_score($rawgrade, $rawmin, $rawmax, $grade_item->grademin, $grade_item->grademax);
+            }*/
+
+            return (int)bounded_number($rawmin, $rawgrade, $grade_item->grademax);
+
+
+        } else if ($grade_item->gradetype == GRADE_TYPE_TEXT or $grade_item->gradetype == GRADE_TYPE_NONE) { // no value
+            // somebody changed the grading type when grades already existed
+            return null;
+
+        } else {
+            debugging("Unknown grade type");
+            return null;
+        }
+    }
+
+
+/**
+ * Pulled from grade_item; regrade grades makes a call to its parent category :(
+ */
+function simple_grade_item_regrade_grades($grade_item, $userid=null, $multiplier=2) {
+        global $CFG;
+
+        // locked grade items already have correct final grades
+        if ($grade_item->is_locked()) {
+            return true;
+        }
+
+        // calculation produces final value using formula from other final values
+        if ($grade_item->is_calculated()) {
+            if ($grade_item->compute($userid)) {
+                return true;
+            } else {
+                return "Could not calculate grades for grade item"; // TODO: improve and localize
+            }
+
+        // noncalculated outcomes already have final values - raw grades not used
+        } else if ($grade_item->is_outcome_item()) {
+            return true;
+
+        // aggregate the category grade
+        } else if ($grade_item->is_category_item() or $grade_item->is_course_item()) {
+            // aggregate category grade item
+            $category = $grade_item->get_item_category();
+            $category->grade_item =& $grade_item;
+            if (simple_category_generate_grades($category, $userid, $multiplier)) {
+                return true;
+            } else {
+                return "Could not aggregate final grades for category:".$grade_item->id; // TODO: improve and localize
+            }
+
+        } /*else if ($grade_item->is_manual_item()) {
+            // manual items track only final grades, no raw grades
+            return true;
+
+        } else if (!$grade_item->is_raw_used()) {
+            // hmm - raw grades are not used- nothing to regrade
+            return true;
+        } */
+
+        // normal grade item - just new final grades
+        $result = true;
+        $grade_inst = new grade_grade();
+        $fields = implode(',', $grade_inst->required_fields);
+        if ($userid) {
+            $rs = get_recordset_select('grade_grades', "itemid={$grade_item->id} AND userid=$userid", '', $fields);
+        } else {
+            $rs = get_recordset('grade_grades', 'itemid', $grade_item->id, '', $fields);
+        }
+        if ($rs) {
+            while ($grade_record = rs_fetch_next_record($rs)) {
+                $grade = new grade_grade($grade_record, false);
+
+                if (!empty($grade_record->locked) or !empty($grade_record->overridden)) {
+                    // this grade is locked - final grade must be ok
+                    continue;
+                }
+
+                $grade->finalgrade = simple_adjust_raw_grade($grade_item, $grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax * $multiplier);
+
+                if (grade_floats_different($grade_record->finalgrade, $grade->finalgrade)) {
+                    if (!$grade->update('system')) {
+                        $result = "Internal error updating final grade";
+                    }
+                }
+            }
+            rs_close($rs);
+        }
+
+        return $result;
+}
+
+/**
+ * Pulled from gradelib; needed for percentages to go over 100
+ */
+function simple_grade_format_gradevalue($value, &$grade_item, $localized=true, $displaytype=null, $decimals=null, $multiplier=2) {
+    if ($grade_item->gradetype == GRADE_TYPE_NONE or $grade_item->gradetype == GRADE_TYPE_TEXT) {
+        return '';
+    }
+
+    // no grade yet?
+    if (is_null($value)) {
+        return '-';
+    }
+
+    if ($grade_item->gradetype != GRADE_TYPE_VALUE and $grade_item->gradetype != GRADE_TYPE_SCALE) {
+        //unknown type??
+        return '';
+    }
+
+    if (is_null($displaytype)) {
+        $displaytype = $grade_item->get_displaytype();
+    }
+
+    if (is_null($decimals)) {
+        $decimals = $grade_item->get_decimals();
+    }
+
+    switch ($displaytype) {
+        case GRADE_DISPLAY_TYPE_REAL:
+            if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+                if (!$scale = $grade_item->load_scale()) {
+                    return get_string('error');
+                }
+
+                $value = (int)bounded_number($grade_item->grademin, $value, $grade_item->grademax * $multiplier);
+                return format_string($scale->scale_items[$value-1]);
+
+            } else {
+                return format_float($value, $decimals, $localized);
+            }
+
+        case GRADE_DISPLAY_TYPE_PERCENTAGE:
+            $min = $grade_item->grademin;
+            $max = $grade_item->grademax;
+            if ($min == $max) {
+                return '';
+            }
+            $value = bounded_number($min, $value, $max * $multiplier);
+            $percentage = (($value-$min)*100)/($max-$min);
+            return format_float($percentage, $decimals, $localized).' %';
+
+        case GRADE_DISPLAY_TYPE_LETTER:
+            $context = get_context_instance(CONTEXT_COURSE, $grade_item->courseid);
+            if (!$letters = grade_get_letters($context)) {
+                return ''; // no letters??
+            }
+
+            $value = grade_grade::standardise_score($value, $grade_item->grademin, $grade_item->grademax, 0, 100);
+            $value = bounded_number(0, $value, 100); // just in case
+            foreach ($letters as $boundary => $letter) {
+                if ($value >= $boundary) {
+                    return format_string($letter);
+                }
+            }
+            return '-'; // no match? maybe '' would be more correct
+
+        default:
+            return '';
+    }
+}
+
+/**
+ * Pulled from grade_categories; I have a method to hook them here
+ */
+function simple_category_generate_grades($grade_category, $userid=null, $multiplier=2) {
+        global $CFG;
+
+        $grade_category->load_grade_item();
+
+        if ($grade_category->grade_item->is_locked()) {
+            return true; // no need to recalculate locked items
+        }
+
+        // find grade items of immediate children (category or grade items) and force site settings
+        $depends_on = $grade_category->grade_item->depends_on();
+
+        if (empty($depends_on)) {
+            $items = false;
+        } else {
+            $gis = implode(',', $depends_on);
+            $sql = "SELECT *
+                      FROM {$CFG->prefix}grade_items
+                     WHERE id IN ($gis)";
+            $items = get_records_sql($sql);
+        }
+
+        if ($userid) {
+            $usersql = "AND g.userid=$userid";
+        } else {
+            $usersql = "";
+        }
+
+        $grade_inst = new grade_grade();
+        $fields = 'g.'.implode(',g.', $grade_inst->required_fields);
+
+        // where to look for final grades - include grade of this item too, we will store the results there
+        $gis = implode(',', array_merge($depends_on, array($grade_category->grade_item->id)));
+        $sql = "SELECT $fields
+                  FROM {$CFG->prefix}grade_grades g, {$CFG->prefix}grade_items gi
+                 WHERE gi.id = g.itemid AND gi.id IN ($gis) $usersql
+              ORDER BY g.userid";
+
+        // group the results by userid and aggregate the grades for this user
+        if ($rs = get_recordset_sql($sql)) {
+            $prevuser = 0;
+            $grade_values = array();
+            $excluded     = array();
+            $oldgrade     = null;
+            while ($used = rs_fetch_next_record($rs)) {
+                if ($used->userid != $prevuser) {
+                    simple_category_aggregate_grades($grade_category, $prevuser, $items, $grade_values, $oldgrade, $excluded, $multiplier);
+                    $prevuser = $used->userid;
+                    $grade_values = array();
+                    $excluded     = array();
+                    $oldgrade     = null;
+                }
+                $grade_values[$used->itemid] = $used->finalgrade;
+                if ($used->excluded) {
+                    $excluded[] = $used->itemid;
+                }
+                if ($grade_category->grade_item->id == $used->itemid) {
+                    $oldgrade = $used;
+                }
+            }
+            simple_category_aggregate_grades($grade_category, $prevuser, $items, $grade_values, $oldgrade, $excluded, $multiplier);//the last one
+            rs_close($rs);
+        }
+
+        return true;
+    
+}
+
+/**
+ * Finally we get to the "offensive" code.  Add those multipliers here
+ */
+function simple_category_aggregate_grades($grade_category, $userid, $items, $grade_values, $oldgrade, $excluded, $multiplier=2) {
+        global $CFG;
+
+        if (empty($userid)) {
+            //ignore first call
+            return;
+        }
+
+        if ($oldgrade) {
+            $oldfinalgrade = $oldgrade->finalgrade;
+            $grade = new grade_grade($oldgrade, false);
+            $grade->grade_item =& $grade_category->grade_item;
+
+        } else {
+            // insert final grade - it will be needed later anyway
+            $grade = new grade_grade(array('itemid'=>$grade_category->grade_item->id, 'userid'=>$userid), false);
+            $grade->grade_item =& $grade_category->grade_item;
+            $grade->insert('system');
+            $oldfinalgrade = null;
+        }
+
+        // no need to recalculate locked or overridden grades
+        if ($grade->is_locked() or $grade->is_overridden()) {
+            return;
+        }
+
+        // can not use own final category grade in calculation
+        unset($grade_values[$grade_category->grade_item->id]);
+
+
+    /// sum is a special aggregation types - it adjusts the min max, does not use relative values
+        if ($grade_category->aggregation == GRADE_AGGREGATE_SUM) {
+            simple_category_sum_grades($grade_category, $grade, $oldfinalgrade, $items, $grade_values, $excluded, $multiplier);
+            return;
+        }
+
+        // if no grades calculation possible or grading not allowed clear final grade
+        if (empty($grade_values) or empty($items) or ($grade_category->grade_item->gradetype != GRADE_TYPE_VALUE and $grade_category->grade_item->gradetype != GRADE_TYPE_SCALE)) {
+            $grade->finalgrade = null;
+            if (!is_null($oldfinalgrade)) {
+                $grade->update('aggregation');
+            }
+            return;
+        }
+
+    /// normalize the grades first - all will have value 0...1
+        // ungraded items are not used in aggregation
+        foreach ($grade_values as $itemid=>$v) {
+            if (is_null($v)) {
+                // null means no grade
+                unset($grade_values[$itemid]);
+                continue;
+            } else if (in_array($itemid, $excluded)) {
+                unset($grade_values[$itemid]);
+                continue;
+            }
+            //Standardized score does not work well with scales as our system doues not support min grades. We simply removed  $items[$itemid]->grademin, and replaced it with 0,
+            $grade_values[$itemid] = grade_grade::standardise_score($v, 0, $items[$itemid]->grademax, 0, 1);
+        }
+
+        // use min grade if grade missing for these types
+        if (!$grade_category->aggregateonlygraded) {
+            foreach($items as $itemid=>$value) {
+                if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) {
+                    $grade_values[$itemid] = 0;
+                }
+            }
+        }
+
+        // limit and sort
+        //$grade_category->apply_limit_rules($grade_values);
+        simple_application_limit_rules($grade_category, $grade_values, $items);
+        asort($grade_values, SORT_NUMERIC);
+
+        // let's see we have still enough grades to do any statistics
+        if (count($grade_values) == 0) {
+            // not enough attempts yet
+            $grade->finalgrade = null;
+            if (!is_null($oldfinalgrade)) {
+                $grade->update('aggregation');
+            }
+            return;
+        }
+
+        // do the maths
+        //We'll try to get some extra credit grade for this category
+        $extra_grade = 0;
+        if (get_field('block', 'id', 'name', 'anonymous_grade')) {
+            require_once($CFG->dirroot . '/blocks/anonymous_grade/lib.php');
+            $extra_grade = get_category_extra_credit_score($grade_values, $items);
+        }
+
+        if ($grade_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) {
+            $agg_grade = simple_aggregate_values($grade_values, $items);
+        } else {
+            $agg_grade = $grade_category->aggregate_values($grade_values, $items);
+        }
+    
+        // recalculate the grade back to requested range
+        $finalgrade = grade_grade::standardise_score($agg_grade, 0, 1, $grade_category->grade_item->grademin, $grade_category->grade_item->grademax);
+
+        //Add extra credt to the final grade
+        $finalgrade = $finalgrade + $extra_grade;
+
+        if (is_null($finalgrade)) {
+            $grade->finalgrade = null;
+        } else {
+            $grade->finalgrade = (float)bounded_number($grade_category->grade_item->grademin, $finalgrade, $grade_category->grade_item->grademax * $multiplier);
+        }
+
+
+        // update in db if changed
+        if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) {
+            $grade->update('aggregation');
+        }
+
+        return;
+    
+}
+
+/**
+ *  This function was taken out of grdae_category->apply_limit_rules;  it now supports
+ *  the simple gradebook XC grades and such.  I don't explicitly check for 
+ *  Weighted Mean, but it should when the simple grade book supports other agg methods
+ */
+function simple_application_limit_rules($category, &$grade_values, $items) {
+    arsort($grade_values, SORT_NUMERIC);
+    $count = 0;
+    if (!empty($category->droplow)) {
+        foreach($grade_values as $itemid=>$grade_value) {
+            if ($count < $category->droplow) {
+                if ($items[$itemid]->aggregationcoef == 0.00000){
+                    continue;
+                }
+                array_pop($grade_values);
+            }
+            $count++;
+        }
+    } else if (!empty($category->keephigh)) {
+        $kept = 0;
+        foreach($grade_values as $itemid=>$grade_value) {
+            // Check for bonus item
+            if ($items[$itemid]->aggregationcoef == 0.00000){
+                continue;
+            }
+
+            if ($kept == $category->keephigh) {
+                unset($grade_values[$itemid]);
+                continue;
+            }
+            $kept++;
+        }
+    }
+}
+
+/**
+ * Aggregate values pulled for simple weighted mean XC
+ */
+function simple_aggregate_values($grade_values, $items) {
+    $weightsum = 0;
+    $sum       = 0;
+    foreach($grade_values as $itemid=>$grade_value) {
+        $weight = $items[$itemid]->grademax - $items[$itemid]->grademin;
+        $aggcoef = $items[$itemid]->aggregationcoef;
+        if ($weight <= 0 || $aggcoef <= 0) {
+            continue;
+        }
+        $weightsum += $weight;
+        $sum       += $weight * $grade_value;
+    }
+    if ($weightsum == 0) {
+        $agg_grade = null;
+    } else {
+        $agg_grade = $sum / $weightsum;
+    }
+    return $agg_grade;
+}
+
+/**
+ * Special sum for sum categories
+ */
+function simple_category_sum_grades($grade_category, &$grade, $oldfinalgrade, $items, $grade_values, $excluded, $multiplier=2) {
+
+        // Determine the new grademax
+        $max = simple_determine_grademax($grade_category, $items, $grade_values);
+
+        if ($grade_category->grade_item->grademax != $max or $grade_category->grade_item->grademin != 0 or $grade_category->grade_item->gradetype != GRADE_TYPE_VALUE){
+            $grade_category->grade_item->grademax = $max;
+            $grade_category->grade_item->grademin = 0;
+            $grade_category->grade_item->gradetype = GRADE_TYPE_VALUE;
+            $grade_category->grade_item->update('aggregation');
+        }
+
+        $sum = array_sum($grade_values);
+        $grade->finalgrade = bounded_number($grade_category->grade_item->grademin, $sum, $grade_category->grade_item->grademax * $multiplier);
+
+        // update in db if changed
+        if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) {
+            $grade->update('aggregation');
+        }
+
+    return;
+}
+
+// Factored out common code
+function simple_determine_grademax($grade_category, $items, &$grade_values) {
+        // ungraded and exluded items are not used in aggregation
+        foreach ($grade_values as $itemid=>$v) {
+            if (is_null($v)) {
+                unset($grade_values[$itemid]);
+            } 
+            /*else if (in_array($itemid, $excluded)) {
+                unset($grade_values[$itemid]);
+            }*/
+        }
+
+        // use 0 if grade missing, droplow used and aggregating all items
+        if (!$grade_category->aggregateonlygraded /*and !empty($grade_category->droplow)*/) {
+            foreach($items as $itemid=>$value) {
+                if (!isset($grade_values[$itemid]) /*and !in_array($itemid, $excluded)*/) {
+                    $grade_values[$itemid] = 0;
+                }
+            }
+        }
+
+        $max = 0;
+
+        //find max grade
+        foreach ($items as $itemid=>$item) {
+            if ($item->aggregationcoef <= 0  /*|| in_array($itemid, $excluded)*/) {
+                // extra credit from this activity - does not affect total
+                continue;
+            }
+            if ($item->gradetype == GRADE_TYPE_VALUE) {
+                $max += $item->grademax;
+            } else if ($item->gradetype == GRADE_TYPE_SCALE) {
+                $max += $item->grademax - 1; // scales min is 1
+            }
+        }
+        
+        return $max;
+}
+?>
Index: grade/report/simple_grader/quick_edit.php
===================================================================
RCS file: grade/report/simple_grader/quick_edit.php
diff -N grade/report/simple_grader/quick_edit.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/quick_edit.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,188 @@
+<?php // $Id: quick_edit.php,v 1.0 2008-05-14 17:03:46 pcali1 Exp $
+
+require_once('../../../config.php');
+require_once('lib/grade_sql.php');
+require_once('quick_edit_table.php');
+require_once('lib/simple_grade_hook.php');
+require_once($CFG->libdir . '/accesslib.php');
+require_once($CFG->libdir . '/grouplib.php');
+require_once($CFG->libdir . '/gradelib.php');
+require_once($CFG->dirroot . '/grade/lib.php');
+
+/**
+ * Author: Philip Cali
+ * Date: 05/01/2008
+ * The post/preprocessor of the quick edit screens
+ * Based on the mode, a different table is generated
+ */
+
+$mode = optional_param('mode', 'course', PARAM_ALPHAEXT);
+$id = required_param('id', PARAM_INT);
+$group = optional_param('group', 0, PARAM_INT);
+$itemid = optional_param('itemid', $id, PARAM_INT);
+$fieldid = optional_param('fieldid', PARAM_INT);
+
+require_login();
+
+if (!$course = get_record('course', 'id', $id)) {
+    //error, invalid course
+    error("Error: Could not load course!");
+}
+
+$course->groupmode = 2;
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+// do some permission checking here;  if they can manage grade, we win!
+require_capability('gradereport/simple_grader:view', $context);
+require_capability('moodle/grade:viewall', $context);
+require_capability('moodle/grade:edit', $context);
+
+// Check to see if we can do anonymous grading
+$anonymous_enabled = false;
+if (get_field('block', 'id', 'name', 'anonymous_grade')){
+    $anonymous_enabled = (get_field('block_anonymous_grade_config', 'value', 'name', 'enable_features') == '1') ? true : false;
+}
+
+// Data is submitted; time to process
+if ($data = data_submitted()) {
+    
+    if ($mode == 'course') {
+        $warnings = course_quick_process($data, $id);
+        $redirect_url = "{$CFG->wwwroot}/grade/report/simple_grader/quick_edit.php?id=$id";
+    } else {
+        // A modified calculation formula
+        $warnings = process_data($data, $id, $mode, $fieldid);
+        $redirect_url = "{$CFG->wwwroot}/grade/report/index.php?id=$id";
+    }
+    
+    // No warnings mean we can populate and check the anonymous grades 
+    if (empty($warnings)){
+        // We need to do some special post-processing if the grade-item is an anonymous grade type
+       if ($mode == 'anonymous' && $anonymous_enabled) {
+            $context = get_context_instance(CONTEXT_COURSE, $course->id);
+            $student_role = get_record('role', 'shortname', 'student');
+
+            $student_count = get_course_students_count($course->id, $context, $student_role);
+            $grade_count = get_grade_item_grade_count($itemid, $course->id);
+            
+            //have all the grades been filled out?
+            if ($student_count <= $grade_count) {
+                $grade_item = get_record('block_anon_grade_items', 'itemid', $itemid);
+                $grade_item->completed = 1;
+
+                update_record('block_anon_grade_items', $grade_item);
+
+                //make the block_anon_grades real grades in moodle's db
+                move_fake_grades_to_real($itemid, $id);
+            }
+       }
+
+       redirect($redirect_url);   
+    }
+}
+
+//print the header
+require_js("{$CFG->wwwroot}/grade/report/simple_grader/functions.js");
+
+$strgrades = get_string('grades');
+$reportname = get_string('modulename', 'gradereport_simple_grader');
+
+$navigation = array(
+              array('name'=> $strgrades, 'link'=>"{$CFG->wwwroot}/grade/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $reportname, 'link'=>"{$CFG->wwwroot}/grade/report/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> 'Quick Edit', 'link' =>'', 'type'=>'title')
+        );
+
+
+if (!empty($warnings)) {
+    foreach($warnings as $warning){
+        notify($warning);
+    }
+}
+
+switch ($mode) {
+    case "user":
+        //print grades for the specified user
+        // in this case, our $items will be grades, and the itemid is the user id
+        $interest = get_record('user', 'id', $itemid);
+        
+        $items = get_real_grades($id);
+        //set the display header
+        $header = fullname($interest);
+
+        $quickedit_form = new quick_edit_user_table($id, $mode);
+        break;
+    case "anonymous":
+        $student_role = get_record('role', 'shortname', 'student');
+        $context = get_context_instance(CONTEXT_COURSE, $course->id);
+        
+        //get all the anonymous students in the course
+        $items = get_anonymous_students_for_course($fieldid, $course->id, $context, $student_role);        
+
+        $grade_item = create_quick_edit_grade_item($itemid, $id);
+
+        //set the display header
+        $header = $grade_item->itemname;
+        $interest = $grade_item;
+
+        $quickedit_form = new quick_edit_anonymous_table($id, $mode, $fieldid);
+        break;
+    case "grades":
+        //print all the users in the course for the specified grade
+        //in this case, our $items will be users, and the itemid is the grade_item id
+        
+        //We first need to block smart users from seeing anonymous grades
+        if ($anonymous_enabled) {
+            $anonymous_grade = get_record('block_anon_grade_items', 'itemid', $itemid);
+            if ($anonymous_grade && !$anonymous_grade->completed){
+                error("This grade is an anonymous grade; please use the system correctly");
+            }
+        }
+
+        // Special sql call for the quick edit screen
+        $grade_item = create_quick_edit_grade_item($itemid, $id);
+
+        // Assumed student role in the system
+        $items = get_role_users(explode(',', $CFG->gradebookroles), 
+             get_context_instance(CONTEXT_COURSE, $course->id), false, '',
+             'u.lastname, u.firstname ASC', true, $group);
+        $groups_select = groups_print_course_menu($course, 
+                "quick_edit.php?id=$id&amp;mode=$mode&amp;itemid=$itemid", true);
+        
+        //set the display header
+        $header = $grade_item->itemname;
+        $interest = $grade_item;
+
+        $quickedit_form = new quick_edit_grade_table($id, $mode);
+        break;
+    default:
+        $header = $course->fullname;
+        $interest = $course;
+        // Retrieve a flattened course tree
+        $items = flatten_tree(grade_category::fetch_course_tree($id));
+        $quickedit_form = new quick_edit_course_table($id, $mode);
+        break;
+}
+
+print_header_simple($header, '', build_navigation($navigation));
+
+print_grade_plugin_selector($id, 'report', 'simple_grader');
+
+// If group are capable of selection, then we print them out?
+if (isset($groups_select)) {
+    echo($groups_select);
+}
+
+// Build our quick edit form data
+$form_data = array('header' => $header,
+                   'interest' => $interest,
+                   'items' => $items);
+
+
+//print out the group_selector
+$quickedit_form->setData($form_data);
+$quickedit_form->display();
+
+print_footer();
+
+?>
Index: grade/report/projected/version.php
===================================================================
RCS file: grade/report/projected/version.php
diff -N grade/report/projected/version.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/version.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,29 @@
+<?PHP // $Id: version.php,v 1.5 2007-10-10 16:09:45 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$plugin->version  = 2008012900;
+$plugin->requires = 2007101000;
+
+?>
Index: grade/report/simple_grader/lang/en_utf8/gradereport_simple_grader.php
===================================================================
RCS file: grade/report/simple_grader/lang/en_utf8/gradereport_simple_grader.php
diff -N grade/report/simple_grader/lang/en_utf8/gradereport_simple_grader.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lang/en_utf8/gradereport_simple_grader.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,16 @@
+<?php
+
+$string['modulename'] = 'Gradebook';
+$string['simple_grader:view'] = 'View the gradebook';
+$string['quick_edit'] = 'QE';
+$string['override'] = 'Override';
+$string['exclude'] = 'Exclude';
+$string['assessment_name'] = 'Assessment Name';
+$string['grade_category'] = 'Grade Category';
+$string['anonymous'] = 'Anonymous Student';
+$string['adjustments'] = 'Adjustments';
+$string['aggregateonlygraded'] = 'Count empty grades as zeroes';
+$string['showstickytab'] = 'Show sticky tab';
+$string['configshowstickytab'] = 'Sticky tabs refer to the position Student names are located when view the report.';
+
+?>
Index: grade/import/mymathlab/mapping.php
===================================================================
RCS file: grade/import/mymathlab/mapping.php
diff -N grade/import/mymathlab/mapping.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/mapping.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,197 @@
+<?php
+
+/**
+ * @author Adam Zapletal
+ * Louisiana State University
+ */
+
+require_once '../../../config.php';
+require_once $CFG->dirroot . '/grade/lib.php';
+require_once $CFG->libdir . '/uploadlib.php';
+
+///////////////////////////////////////////////////////////////////////////////
+
+$id = required_param('id', PARAM_INT); // course id
+
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+
+echo require_js(array('yui_yahoo', 'yui_dom-event', 'yui_animation', 'yui_event', 
+                      'yui_connection', 'functions.js'));
+
+$context = get_context_instance(CONTEXT_COURSE, $id);
+
+require_capability('moodle/grade:import', $context);
+require_capability('gradeimport/mymathlab:view', $context);
+
+$CFG->stylesheets[] = $CFG->wwwroot . '/grade/import/mymathlab/style.css';
+
+$actionstr = get_string('modulename', 'gradeimport_mymathlab');
+$navigation = grade_build_nav(__FILE__, $actionstr, array('courseid' => $course->id));
+
+print_header($course->shortname.': '.get_string('grades'), $course->fullname, $navigation);
+print_grade_plugin_selector($id, 'import', 'mymathlab');
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Load file
+$um = new upload_manager('mymathlab_file', false, false, $course, false, 0, true);
+
+if ($um->preprocess_files()) {
+    $lines = file($um->files['mymathlab_file']['tmp_name']);
+} else {
+    $error_text = get_string('file_error', 'gradeimport_mymathlab');
+    echo '<div class = "error">' . $error_text . '</div>';
+    print_footer();
+    die();
+}
+
+$keepers = array();
+$math_ids_to_grades = array();
+
+// Chop the file up into meaningful data
+foreach ($lines as $line) {
+    if ($line[0] == '"') {
+        $keepers[] = explode(',', str_replace('"', '', trim($line)));
+    }   
+}
+
+if (!$keepers) {
+    $error_text = get_string('validation_error', 'gradeimport_mymathlab');
+    echo '<div class = "error">' . $error_text . '</div>';
+    print_footer();
+    die();
+}
+
+// Split up the first line of the file into grade item names
+$raw_parts = explode(',"', trim($lines[0]));
+$tmp_grade_fields = array_slice($raw_parts, 1, count($raw_parts) - 1, True);
+$grade_fields = array();
+
+// Adding 4 to the key makes it match the field number in the input file.
+// This is necessary because later I use the field index to key grade values.
+// This seems convoluted because it allows for commas inside of grade item names.
+foreach ($tmp_grade_fields as $k => $grade_field) {
+    $grade_fields[$k + 4] = rtrim($grade_field, '",');
+}
+
+// Build grade item selector
+$items = get_records('grade_items', 'courseid', $id, 'itemname asc', 
+                     'id, itemname, itemtype');
+
+$select_item = get_string('select_item', 'gradeimport_mymathlab');
+$item_options = array('<option value = 0>' . $select_item . '</option>');
+
+foreach ($items as $item) {
+    if ($item->itemtype == 'manual') {
+        $item_options[] = "<option value = $item->id >$item->itemname </option>";
+    }
+}
+
+// Prepare and echo form
+$math_header = get_string('math_grades_header', 'gradeimport_mymathlab');
+$moodle_header = get_string('moodle_grades_header', 'gradeimport_mymathlab');
+$map_to = get_string('map_to', 'gradeimport_mymathlab');
+
+$action = 'import.php?id=' . $id;
+
+echo "
+<div id = 'error' class = 'error'>&nbsp;</div>
+<div class = 'mapping_form'>
+<form enctype = 'multipart/form-data' action = $action method = 'post' onsubmit = 'return validate_mapping();'>
+    <div class = 'header_row'>
+        <span class = 'math_grades_header'>" . $math_header . "</span>
+        <span class = 'header_spacer'></span>
+        <span class = 'moodle_grades_header'>" . $moodle_header . "</span>
+    </div>
+";
+
+// Map moodle user ids to pawsids (usernames)
+$usernames_to_moodle_ids = array();
+$roleid = get_field('role', 'id', 'shortname', 'student');
+$userdata = get_role_users($roleid, $context, false, 'u.id, u.username');
+$error = array();
+
+foreach ($userdata as $id => $data) {
+    $usernames_to_moodle_ids[$data->username] = $id;
+}
+
+foreach ($grade_fields as $k => $grade_field) {
+    foreach ($keepers as $fields) {
+        if (!isset($fields[$k]) or !$fields[$k]) {
+            continue;
+        }   
+
+        list($pawsid, $suffix) = explode('@', $fields[2]);
+
+        if (in_array($pawsid, array_keys($usernames_to_moodle_ids))) {
+            $math_ids_to_grades[$k][$usernames_to_moodle_ids[$pawsid]] = $fields[$k];
+        } else {
+            $error[] = $pawsid . ' ' . get_string('skip', 'gradeimport_mymathlab');;
+        }
+    }   
+
+    echo "
+    <div class = 'mapping_row'>
+        <span class = 'math_grade'>$grade_field</span>
+        <span class = 'map_to'>$map_to</span>
+        <span class = 'moodle_grade'>
+            <select name = 'grade_mapping_$k' class = 'mapping_select'>" . 
+                implode("\n", $item_options) .
+           "</select>
+        </span>
+    </div>
+    ";
+}
+
+if ($error) {
+    echo '<div id = "enrollment_error" class = "error">';
+    echo implode("<br />\n", array_unique($error)) . '</div>';
+}
+
+
+// MyMathLab can output either 0.60 or 60.0 per file. If we find that
+// the file has the 0.60 format, we will multiply all values by 100
+// before processing.
+$percents = False;
+
+foreach ($math_ids_to_grades as $grades) {
+    foreach ($grades as $id => $finalgrade) {
+        if ($finalgrade > 2.00) {
+            $percents = True;
+        }
+    }
+}
+
+if (!$percents) {
+    foreach ($math_ids_to_grades as $k => $grades) {
+        foreach ($grades as $id => $finalgrade) {
+            $math_ids_to_grades[$k][$id] = $finalgrade * 100;
+        }
+    }
+
+    $converted_text = get_string('converted', 'gradeimport_mymathlab');
+    echo '<div class = "converted_alert">' . $converted_text . '</div>';
+}
+
+
+$SESSION->mymathlab_grades = $math_ids_to_grades;
+
+$button_string = get_string('map_grades', 'gradeimport_mymathlab');
+
+echo "
+    <div class = 'mapping_submit'>
+        <input type = 'submit' value = '$button_string'/>
+    </div>
+</form>    
+</div>
+";
+
+///////////////////////////////////////////////////////////////////////////////
+
+print_footer();
+
+?>
Index: grade/report/simple_grader/lib/grade_sql.php
===================================================================
RCS file: grade/report/simple_grader/lib/grade_sql.php
diff -N grade/report/simple_grader/lib/grade_sql.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lib/grade_sql.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,144 @@
+<?php // $Id: grade_sql.php,v 1.0 2008-05-14 17:03:46 pcali1 Exp $
+
+/**
+ * Author: Philip Cali
+ * This is a little library file, with specialized and optimized db queries
+ * particularly from the quick edit screens
+ */
+
+function flatten($category, $item_arr) {
+    $array = Array();
+
+    if (empty($item_arr)) {
+        return $array;
+    }
+
+    $item = array_pop($item_arr);
+    if (get_class($item['object']) == 'grade_item') {
+        $item['object']->aggregation = $category->aggregation;
+        $array[$item['object']->id] = $item['object'];
+    }
+    $array = flatten($category, $item_arr) + $array;
+    $array += flatten($item['object'], $item['children']);
+    return $array;
+    
+}
+
+function flatten_tree($tree) {
+    $arr = Array();
+    $arr += flatten($tree['object'], $tree['children']);
+    return $arr;
+}
+
+
+/**
+ * This sql generates "real" grade items, not ones that are anonymous
+ * or completed anonymous grades
+ * @param $courseid the course id
+ * @return $items items from the query
+ */
+function get_real_grades($courseid, $all = false, $sorted='sortorder') {
+    global $CFG;
+   
+    $selected_str = '';
+    $existed = get_field('block', 'id', 'name', 'anonymous_grade');
+    if (!$all && $existed) {
+        $select_str = "AND i.id NOT IN (
+                       SELECT a.itemid FROM {$CFG->prefix}block_anon_grade_items a)";
+                        
+    }
+ 
+    $grade_item_sql = "SELECT i.*, c.fullname, c.aggregation FROM 
+             {$CFG->prefix}grade_items i, 
+             {$CFG->prefix}grade_categories c 
+             WHERE i.courseid={$courseid} and i.categoryid=c.id 
+             $selected_str
+             ORDER BY i.{$sorted}";
+
+    $items = get_records_sql($grade_item_sql);
+    return $items;
+}
+
+function create_quick_edit_grade_item($itemid, $courseid) {
+   $grade_item = grade_item::fetch(array('id'=> $itemid, 'courseid'=>$courseid));
+   $grade_item->completed = get_field('block_anon_grade_items', 'completed', 'itemid', $grade_item->id);
+   
+   $grade_category = $grade_item->get_parent_category();
+
+   $grade_item->aggregation = $grade_category->aggregation;
+
+   return $grade_item;
+}
+
+/**
+ * This returns the students and their anonymous profile associated with them
+ * @param $fieldid id of the custom profile field
+ * @param $courseid id of the course in question
+ * @param $context the context to grab the students; if null, will build it's own context
+ * @param $studentrole the role id of the student role
+ * @return $items items from which the query returns
+ */
+function get_anonymous_students_for_course($fieldid, $courseid, $context=null, $student_role=null) {
+        global $CFG;
+        if ($student_role == null){ 
+            $student_role = get_record('role', 'shortname', 'student');
+        }
+        if ($context == null){
+            $context = get_context_instance(CONTEXT_COURSE, $courseid);
+        }
+
+        $item_sql = "SELECT u.id, p.data FROM {$CFG->prefix}role_assignments ra 
+                     JOIN {$CFG->prefix}user u on u.id = ra.userid 
+                     JOIN {$CFG->prefix}role r on ra.roleid = r.id 
+                     JOIN {$CFG->prefix}user_info_data p on p.userid = u.id 
+                            AND p.fieldid = $fieldid 
+                        WHERE ra.contextid = {$context->id} 
+                            AND ra.roleid = {$student_role->id} order by p.data";
+
+        $items = get_records_sql($item_sql);
+        return $items;
+}
+
+/**
+ * Function returns the number of students in a course
+ * @param $courseid id of the course in question
+ * @param $context context to query; if null will default to CONTEXT_COURSE
+ * @param $student_role id of the student role; if null defaults to student
+ * @return the number of students in the course
+ */
+function get_course_students_count($courseid, $context=null, $student_role=null) {
+     global $CFG;
+     if ($student_role == null){ 
+         $student_role = get_record('role', 'shortname', 'student');
+     }
+     if ($context == null){
+         $context = get_context_instance(CONTEXT_COURSE, $courseid);
+     }
+
+     $student_count_sql = "SELECT count(u.id) FROM {$CFG->prefix}role_assignments ra 
+         JOIN {$CFG->prefix}user u on u.id = ra.userid 
+         JOIN {$CFG->prefix}role r on ra.roleid = r.id 
+              WHERE ra.contextid = {$context->id} 
+                AND ra.roleid = {$student_role->id} ";
+
+     return count_records_sql($student_count_sql);        
+}
+
+/**
+ * This function returns the number of grades for a grade items
+ * @param $courseid id the course in question
+ * @param $itemid id the grade item in question
+ * @param $context context to query
+ * @param $student_role id of the student role
+ */
+function get_grade_item_grade_count($itemid, $courseid){
+     global $CFG;
+     
+    $grade_count_sql = "SELECT count(gr.id) FROM {$CFG->prefix}grade_items gi
+         JOIN {$CFG->prefix}block_anon_grade_grades gr on gr.itemid = gi.id
+            WHERE gi.id = $itemid 
+            AND gi.courseid = {$courseid}";
+    return count_records_sql($grade_count_sql);
+}
+
+?>
Index: grade/report/simple_grader/INSTALL.txt
===================================================================
RCS file: grade/report/simple_grader/INSTALL.txt
diff -N grade/report/simple_grader/INSTALL.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/INSTALL.txt	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,155 @@
+********************************
+*    INSTALLTION NOTES         *
+********************************
+
+For a full installation of the simple grader, you will need the following:
+
+    A) The Grade Features block. Copy the contents blocks/anonymous_grade to {MOODLE_ROOT}/blocks/anonymous_grade.
+      1) As an admin, click the Notifications link, and have Moodle build the tables needed for extra grade features.
+      2) Once the block successfully installs, navigate to the config page of the Grade Features block. The quickest way
+        to get there is through the Site Administration Block Modules->Blocks->Grade Features, and click on "Enable Extra Grade Features". 
+        At the configuration page, you should be presented a couple of checkboxes, and select boxes. For now, 
+        check the "Enable Extra Grade Features" and "Extra Credit for Weighted and Simple Weighted Mean" checkboxes. 
+        Save Changes, and you're through setting up the Grade Features block.
+
+    B) Copy the contents of grade/edit/simple_tree to {MOODLE_ROOT}/grade/edit/simple_tree
+
+    C) Copy the contents of grade/edit/custom_letters to {MOODLE_ROOT}/grade/edit/custom_letters
+
+    C) Copy the contents of grade/report/simple_grader tp {MOODLE_ROOT}/grade/report/simple_grader.
+
+
+********************************
+*     POST INSTALLATION        *
+*    THESE MUST BE DONE!       *
+********************************
+
+In order to take advantage of all the features of Simple Grader, some minor changes outside the report must take place.
+
+    A) The header.html of the current theme must be changed to look for the javascript in simple_grader/lib/menufixer.php.
+    The header html file is located in {MOODLE_ROOT}/theme/{CURRENT_THEME}/header.html.  This hack is required to change
+    the grade report plugin selector to route to the new modules.
+    Below is how the beginning of your theme header should look:
+    
+<head>
+    ....
+
+    <?php $filenamejs = "$CFG->dirroot/grade/report/simple_grader/lib/menufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } ?>
+
+</head>
+
+<body<?php
+    echo " $bodytags";
+    if ($focus) {
+        echo " onload=\"setfocus()\"";
+    }else {
+	echo " onload=\"replace_plugin()\"";
+    }
+    ?>>
+  ....
+   
+    B) Some core changes must take place in order for the calcucation to be affected across
+    the board. 
+    NOTE: These core change notes can also be found in README.txt
+
+        1) The default aggregation coefficient must be set to 1 in {MOODLE_ROOT}/lib/grade/grade_item.php
+        Around line 197:
+        var $aggregationcoef = 0; => var $aggregationcoef = 1;
+        Note: The line number may not be exact in your version, but it should be close.
+
+        The new gradebook treats everything that has an aggregation coefficient of 0 to be an extra credit
+        grade. Originally, Sums with an aggregation of 0 were considered real, and 1 were extra credit, but
+        Weighted Mean, would not share the same logic.
+
+        2) Add a check for Simple Grader report to gradelib, located in
+        {MOODLE_ROOT}/lib/gradelib.php
+        At the very beginning of the function grade_regrade_final_grade, you must add code that calculates core modules correctly.
+        So, the code below must be added right under the function declaration line which looks something like:
+        function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) { 
+        
+        // Check for Simple Grader Report
+        global $CFG;
+             
+        $exists = file_exists($CFG->dirroot. '/grade/report/simple_grader/lib/simple_gradelib.php');
+        if ($exists) {
+             require_once($CFG->dirroot . '/grade/report/simple_grader/lib/simple_gradelib.php');
+             return simple_grade_regrade_final_grades($courseid, $userid, $updated_item);
+        }   
+        // End check for Simple Grader Report
+
+        The new gradebook allows for more richly calculated methods than the original gradebook, and when a mod's grade
+        was submitted, it would run through the original's function
+
+        3) Check for simple_grader in {MOODLE_ROOT}/grade/report/index.php
+        towards the end of the file.
+
+        Change the following lines from:
+
+         if (empty($last)) {
+             if (in_array('grader', $reports)) {
+                 $last = 'grader';
+             }
+
+        to:
+
+         if (empty($last)) {
+             if (in_array('simple_grader', $reports)) {
+                 $last = 'simple_grader';
+             }
+
+        This is required if you plan to replace the original gradebook. Ideally, the admin would disable the original
+        gradebook, and apply this change so that teachers would route to the new gradebook, as opposed to their user report.
+
+        4) Add a similar check in {MOODLE_ROOT}/grade/import/lib.php
+         around line 55 in function grade_import_commit add the following:
+             
+            $use_function = false;
+            $file = $CFG->dirroot . '/grade/report/simple_grader/lib/simple_gradelib.php';
+            if (file_exists($file)) {
+                require_once($file);
+                $use_function = true;
+            }
+         
+         Then jump to around line 82:
+            ....
+            // insert each individual grade to this new grade item
+            foreach ($grades as $grade) {
+                if ($use_function){
+                    if(!simple_update_final_grade($grade->userid, $gradeitem, 2, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
+                        $failed = true;
+                        break 2;
+                    }
+                } else if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
+                    $failed = true;
+                    break 2;
+                }
+            }
+          And lastly around line 125:
+            ....
+            // make the grades array for update_grade
+            foreach ($grades as $grade) {
+                if (!$importfeedback) {
+                    $grade->feedback = false; // ignore it
+                }
+                if ($use_function){
+                    if(!simple_update_final_grade($grade->userid, $gradeitem, 2, $grade->finalgrade, 'import', $grade->feedback)) {
+                        $failed = true;
+                        break 2;
+                    }
+                } else if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback)) {
+                    $failed = 1;
+                    break 2;
+                }
+            }
+
+        Unfortunately, this is the biggest core change. Import uses gradeitem->update_final_grade, and all occurences of grade_import_commit
+        must be changed to use the new system.
+
+    C) Denying access to the original grader report. Fortunately, this can be done in Moodle, defining capabilities.
+        With the Site Administration block navigate to Users->Permissions->Define Roles. For every role, change the 
+        gradereport/grader:view to "Not Set"
+
+        This will deny access to the original gradebook.
+
+    Once you've completed the changes, your system is now setup with a simpler, more featureful gradebook.
Index: grade/report/simple_grader/preferences.php
===================================================================
RCS file: grade/report/simple_grader/preferences.php
diff -N grade/report/simple_grader/preferences.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/preferences.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,104 @@
+<?php // $Id: preferences.php,v 1.25.2.3 2007-12-19 17:38:46 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas  http://dougiamas.com     //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali
+ * Changed the url and capability to support the simple grader
+ */
+
+set_time_limit(0);
+require_once '../../../config.php';
+require_once $CFG->libdir . '/gradelib.php';
+require_once '../../lib.php';
+
+$courseid      = required_param('id', PARAM_INT);
+
+/// Make sure they can even access this course
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course->id);
+
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+$systemcontext = get_context_instance(CONTEXT_SYSTEM);
+require_capability('gradereport/simple_grader:view', $context);
+
+require('preferences_form.php');
+$mform = new grader_report_preferences_form('preferences.php', compact('course'));
+
+if ($mform->is_cancelled()){
+    redirect($CFG->wwwroot . '/grade/report/simple_grader/index.php?id='.$courseid);
+}
+
+// If data submitted, then process and store.
+if ($data = $mform->get_data()) {
+    foreach ($data as $preference => $value) {
+        if (substr($preference, 0, 6) !== 'grade_') {
+            continue;
+        }
+
+        if ($value == GRADE_REPORT_PREFERENCE_DEFAULT || strlen($value) == 0) {
+            unset_user_preference($preference);
+        } else {
+            set_user_preference($preference, $value);
+        }
+    }
+
+    redirect($CFG->wwwroot . '/grade/report/simple_grader/index.php?id='.$courseid); // message here breaks accessability and is sloooowww
+    exit;
+}
+
+$strgrades = get_string('grades');
+$strgraderreport = get_string('modulename', 'gradereport_simple_grader');
+$strgradepreferences = get_string('gradepreferences', 'grades');
+
+$navigation = grade_build_nav(__FILE__, $strgradepreferences, $courseid);
+
+print_header_simple($strgrades.': '.$strgraderreport . ': ' . $strgradepreferences,': '.$strgradepreferences, $navigation,
+                    '', '', true, '', navmenu($course));
+
+/// Print the plugin selector at the top
+print_grade_plugin_selector($course->id, 'report', 'simple_grader');
+
+// Add tabs
+$currenttab = 'preferences';
+include('tabs.php');
+
+// If USER has admin capability, print a link to the site config page for this report
+if (has_capability('moodle/site:config', $systemcontext)) {
+    echo '<div id="siteconfiglink"><a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=gradereportsimple_grader">';
+    echo get_string('changereportdefaults', 'grades');
+    echo "</a></div>\n";
+}
+
+print_simple_box_start("center");
+
+$mform->display();
+print_simple_box_end();
+
+print_footer($course);
+?>
Index: grade/report/simple_grader/preferences_form.php
===================================================================
RCS file: grade/report/simple_grader/preferences_form.php
diff -N grade/report/simple_grader/preferences_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/preferences_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,218 @@
+<?php  //$Id: preferences_form.php,v 1.40.3.0 2008-03-19 16:16:20 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali
+ */
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * First implementation of the preferences in the form of a moodleform.
+ * TODO add "reset to site defaults" button
+ */
+class grader_report_preferences_form extends moodleform {
+
+    function definition() {
+        global $USER, $CFG;
+
+        $mform    =& $this->_form;
+        $course   = $this->_customdata['course'];
+
+        $context = get_context_instance(CONTEXT_COURSE, $course->id);
+        $systemcontext = get_context_instance(CONTEXT_SYSTEM);
+
+        $strgradeboundary       = get_string('gradeboundary', 'grades');
+        $strconfiggradeboundary = get_string('configgradeboundary', 'grades');
+        $strgradeletter         = get_string('gradeletter', 'grades');
+        $strconfiggradeletter   = get_string('configgradeletter', 'grades');
+        $stryes                 = get_string('yes');
+        $strno                  = get_string('no');
+
+        $canviewhidden = has_capability('moodle/grade:viewhidden', $context);
+
+
+        $checkbox_default = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*', 0 => $strno, 1 => $stryes);
+
+        $advanced = array();
+/// form definition with preferences defaults
+//--------------------------------------------------------------------------------
+        $preferences = array();
+
+        // Initialise the preferences arrays with grade:manage capabilities
+        if (has_capability('moodle/grade:manage', $context)) {
+            $preferences['prefgeneral'] = array(
+                          'aggregationview'     => array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                         GRADE_REPORT_AGGREGATION_VIEW_FULL => get_string('fullmode', 'grades'),
+                                                         GRADE_REPORT_AGGREGATION_VIEW_AGGREGATES_ONLY => get_string('aggregatesonly', 'grades'),
+                                                         GRADE_REPORT_AGGREGATION_VIEW_GRADES_ONLY => get_string('gradesonly', 'grades')));
+
+
+            $preferences['prefgeneral']['showstickytab'] = $checkbox_default;
+            $preferences['prefshow'] = array();
+            $preferences['prefshow']['showeyecons']       = $checkbox_default;
+            if ($canviewhidden) {
+                $preferences['prefshow']['showaverages']  = $checkbox_default;
+            }
+            $preferences['prefshow']['showlocks']         = $checkbox_default;
+
+            $preferences['prefrows'] = array(
+                        'rangesdisplaytype'      => array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                          GRADE_REPORT_PREFERENCE_INHERIT => get_string('inherit', 'grades'),
+                                                          GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'),
+                                                          GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'),
+                                                          GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades')),
+                        'rangesdecimalpoints'    => array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                          GRADE_REPORT_PREFERENCE_INHERIT => get_string('inherit', 'grades'),
+                                                          0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5));
+            $advanced = array_merge($advanced, array('rangesdisplaytype', 'rangesdecimalpoints'));
+
+            if ($canviewhidden) {
+                $preferences['prefrows']['averagesdisplaytype'] = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                                        GRADE_REPORT_PREFERENCE_INHERIT => get_string('inherit', 'grades'),
+                                                                        GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'),
+                                                                        GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'),
+                                                                        GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades'));
+                $preferences['prefrows']['averagesdecimalpoints'] = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                                          GRADE_REPORT_PREFERENCE_INHERIT => get_string('inherit', 'grades'),
+                                                                          0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
+                $preferences['prefrows']['meanselection']  = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                                   GRADE_REPORT_MEAN_ALL => get_string('meanall', 'grades'),
+                                                                   GRADE_REPORT_MEAN_GRADED => get_string('meangraded', 'grades'));
+
+                $advanced = array_merge($advanced, array('averagesdisplaytype', 'averagesdecimalpoints'));
+            }
+        }
+
+        // quickgrading and showquickfeedback are conditional on grade:edit capability
+        if (has_capability('moodle/grade:edit', $context)) {
+            // Removed this feature because it was confusing teachers
+            //$preferences['prefgeneral']['quickgrading'] = $checkbox_default;
+            $preferences['prefgeneral']['showquickfeedback'] = $checkbox_default;
+        }
+
+        // View capability is the lowest permission. Users with grade:manage or grade:edit must also have grader:view
+        if (has_capability('gradereport/simple_grader:view', $context)) {
+            $preferences['prefgeneral']['studentsperpage'] = 'text';
+            $preferences['prefgeneral']['aggregationposition'] = array(GRADE_REPORT_PREFERENCE_DEFAULT => '*default*',
+                                                                       GRADE_REPORT_AGGREGATION_POSITION_FIRST => get_string('positionfirst', 'grades'),
+                                                                       GRADE_REPORT_AGGREGATION_POSITION_LAST => get_string('positionlast', 'grades'));
+            // $preferences['prefgeneral']['enableajax'] = $checkbox_default;
+
+            $preferences['prefshow']['showuserimage'] = $checkbox_default;
+            $preferences['prefshow']['showuseridnumber'] = $checkbox_default;
+            $preferences['prefshow']['showactivityicons'] = $checkbox_default;
+            $preferences['prefshow']['showranges'] = $checkbox_default;
+
+            if ($canviewhidden) {
+                $preferences['prefrows']['shownumberofgrades'] = $checkbox_default;
+            }
+
+            $advanced = array_merge($advanced, array('aggregationposition'));
+        }
+
+
+        foreach ($preferences as $group => $prefs) {
+            $mform->addElement('header', $group, get_string($group, 'grades'));
+
+            foreach ($prefs as $pref => $type) {
+                // Detect and process dynamically numbered preferences
+                if (preg_match('/([^[0-9]+)([0-9]+)/', $pref, $matches)) {
+                    $lang_string = $matches[1];
+                    $number = ' ' . $matches[2];
+                } else {
+                    $lang_string = $pref;
+                    $number = null;
+                }
+
+                $full_pref  = 'grade_report_simple_' . $pref;
+
+                $pref_value = get_user_preferences($full_pref);
+
+                $options = null;
+                if (is_array($type)) {
+                    $options = $type;
+                    $type = 'select';
+                    // MDL-11478
+                    // get default aggregationposition from grade_settings
+                    if (!empty($CFG->{$full_pref})) {
+                    $course_value = grade_get_setting($course->id, $pref, $CFG->{$full_pref});
+                    }
+                    
+                    if ($pref == 'aggregationposition') {
+                        if (!empty($options[$course_value])) {
+                            $default = $options[$course_value];
+                        } else {
+                            $default = $options[$CFG->grade_aggregationposition];
+                        }
+                    } elseif (isset($options[$CFG->{$full_pref}])) {
+                        $default = $options[$CFG->{$full_pref}];
+                    } else {
+                        $default = '';
+                    }
+                } else {
+                    $default = $CFG->$full_pref;
+                }
+
+                $help_string = get_string("config$lang_string", 'grades');
+
+                // Replace the '*default*' value with the site default language string - 'default' might collide with custom language packs
+                if (!is_null($options) AND isset($options[GRADE_REPORT_PREFERENCE_DEFAULT]) && $options[GRADE_REPORT_PREFERENCE_DEFAULT] == '*default*') {
+                    $options[GRADE_REPORT_PREFERENCE_DEFAULT] = get_string('reportdefault', 'grades', $default);
+                } elseif ($type == 'text') {
+                    $help_string = get_string("config{$lang_string}default", 'grades', $default);
+                }
+
+                $label = get_string($lang_string, 'grades') . $number;
+                if ($lang_string == 'showstickytab'){
+                    $label = get_string($lang_string, 'gradereport_simple_grader') . $number;
+                }
+
+                $mform->addElement($type, $full_pref, $label, $options);
+                if ($lang_string != 'showuserimage' && $lang_string != 'showstickytab') {
+                    $mform->setHelpButton($full_pref, array($lang_string, get_string($lang_string, 'grades'), 'grade'), true);
+                }
+                $mform->setDefault($full_pref, $pref_value);
+                $mform->setType($full_pref, PARAM_ALPHANUM);
+            }
+        }
+
+        foreach($advanced as $name) {
+            $mform->setAdvanced('grade_report_simple_'.$name);
+        }
+
+        $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
+        $mform->setDefault('id', $course->id);
+
+        $this->add_action_buttons();
+    }
+
+/// perform some extra moodle validation
+    function validation($data, $files) {
+        return parent::validation($data, $files);
+    }
+}
+?>
Index: grade/edit/simple_tree/README.txt
===================================================================
RCS file: grade/edit/simple_tree/README.txt
diff -N grade/edit/simple_tree/README.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/README.txt	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,9 @@
+*******************************************************************************
+* INSTALL                                                                     *
+*******************************************************************************
+
+To install the simple_tree plugin, copy the the simple_tree
+directory to {MOODLE_BASE}/grade/edit/
+
+This module includes extra help files. Copy them from the lang directory to 
+{MOODLE_BASE}/lang/{YOUR LANGUAGE}/grade
Index: grade/edit/simple_tree/action.php
===================================================================
RCS file: grade/edit/simple_tree/action.php
diff -N grade/edit/simple_tree/action.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/action.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,108 @@
+<?php  // $Id: action.php,v 1.5 2007-10-10 06:34:20 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+
+$courseid = required_param('id', PARAM_INT);
+$action   = required_param('action', PARAM_ALPHA);
+$eid      = required_param('eid', PARAM_ALPHANUM);
+
+/// Make sure they can even access this course
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+// default return url
+$gpr = new grade_plugin_return();
+$returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/edit/tree/index.php?id='.$course->id);
+
+// get the grading tree object
+$gtree = new grade_tree($courseid, false, false);
+
+// what are we working with?
+if (!$element = $gtree->locate_element($eid)) {
+    error('Incorrect element id!', $returnurl);
+}
+$object = $element['object'];
+$type   = $element['type'];
+
+
+switch ($action) {
+    case 'hide':
+        if ($eid and confirm_sesskey()) {
+            if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
+                error('No permission to hide!', $returnurl);
+            }
+            if ($type == 'grade' and empty($object->id)) {
+                $object->insert();
+            }
+            $object->set_hidden(1, true);
+        }
+        break;
+
+    case 'show':
+        if ($eid and confirm_sesskey()) {
+            if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
+                error('No permission to show!', $returnurl);
+            }
+            if ($type == 'grade' and empty($object->id)) {
+                $object->insert();
+            }
+            $object->set_hidden(0, true);
+        }
+        break;
+
+    case 'lock':
+        if ($eid and confirm_sesskey()) {
+            if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context)) {
+                error('No permission to lock!', $returnurl);
+            }
+            if ($type == 'grade' and empty($object->id)) {
+                $object->insert();
+            }
+            $object->set_locked(1, true, true);
+        }
+        break;
+
+    case 'unlock':
+        if ($eid and confirm_sesskey()) {
+            if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context)) {
+                error('No permission to unlock!', $returnurl);
+            }
+            if ($type == 'grade' and empty($object->id)) {
+                $object->insert();
+            }
+            $object->set_locked(0, true, true);
+        }
+        break;
+}
+
+redirect($returnurl);
+//redirect($returnurl, 'debug delay', 5);
+
+?>
Index: blocks/anonymous_grade/enable_form.php
===================================================================
RCS file: blocks/anonymous_grade/enable_form.php
diff -N blocks/anonymous_grade/enable_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/enable_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+<?php // $Id: enable_form.php,v 1.0 2008/05/14 09:53:43 pcali1 Exp $
+
+require_once($CFG->libdir . '/formslib.php');
+
+class enable_form extends moodleform {
+
+    function definition() {
+        global $CFG, $USER;
+
+        $form = &$this->_form;
+
+        //get all the custom profile fields in this particular system
+        $profile_fields = $this->fill_selects_appropriately('user_info_field');
+
+        // get all the course_categories in the this system
+        $course_categories = $this->fill_selects_appropriately('course_categories');
+
+        $form->addElement('header', 'enable_header', get_string('extra_features', 
+                        'block_anonymous_grade'));
+        $form->addElement('checkbox', 'enable_features', get_string('extra_features', 
+                    'block_anonymous_grade'), '');
+
+        $form->addElement('select', 'profileid', get_string('anonymous_field', 
+                        'block_anonymous_grade'), $profile_fields);
+        $form->addElement('select', 'limit_category', get_string('limit_category', 
+                    'block_anonymous_grade'), $course_categories);
+        $form->addElement('static', 'profile_link', '', '<a href="'.$CFG->wwwroot.
+                    '/user/profile/index.php">Create a user profile</a>');
+        $form->addElement('text', 'max_adjust_value', get_string('limit_adjust', 
+                    'block_anonymous_grade'));
+        $form->addElement('checkbox', 'extra_credit', '', get_string('extra_credit', 
+                    'block_anonymous_grade'));
+        $form->disabledIf('max_adjust_value', 'enable_features');
+        $form->disabledIf('limit_category', 'enable_features');
+        $form->disabledIf('profileid', 'enable_features');
+        $form->disabledIf('extra_credit', 'enable_features');
+               
+ 
+        $buttonarry = array();
+        $buttonarry[] = &$form->createElement('submit', 'submitbutton', get_string('savechanges'));
+        $buttonarry[] = &$form->createElement('cancel');
+        $form->addGroup($buttonarry, 'buttonarr', '', array(' '), false);
+    }
+
+    /**
+     * An abstract function that takes in a table and fills an array
+     * appropriately for a moodle select
+     */
+    function fill_selects_appropriately($table) {
+        $fields = get_records($table);
+        //if there are fields entries, iterate over them and prepend the none item
+        if ($fields) {
+            foreach ($fields as $key => $field) {
+                $fields[$key] = $field->name;
+            }
+            $fields = array('0' => get_string('none')) + $fields;
+        }
+        // Otherwise, just make an aray with the default none item 
+        else {
+            $fields = array('0' => get_string('none'));
+        }
+        return $fields;
+    }
+
+}
+
+?>
Index: grade/edit/simple_tree/outcomeitem.php
===================================================================
RCS file: grade/edit/simple_tree/outcomeitem.php
diff -N grade/edit/simple_tree/outcomeitem.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/outcomeitem.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,219 @@
+<?php  //$Id: outcomeitem.php,v 1.15.2.5 2008-03-22 21:19:09 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/lib.php';
+require_once 'outcomeitem_form.php';
+
+$courseid = required_param('courseid', PARAM_INT);
+$id       = optional_param('id', 0, PARAM_INT);
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+require_capability('moodle/grade:manage', $context);
+
+
+// default return url
+$gpr = new grade_plugin_return();
+$returnurl = $gpr->get_return_url('index.php?id='.$course->id);
+
+$mform = new edit_outcomeitem_form(null, array('gpr'=>$gpr));
+
+if ($mform->is_cancelled() || empty($CFG->enableoutcomes)) {
+    redirect($returnurl);
+}
+
+if ($grade_item = grade_item::fetch(array('id'=>$id, 'courseid'=>$courseid))) {
+    // redirect if outcomeid present
+    if (empty($grade_item->outcomeid)) {
+        $url = $CFG->wwwroot.'/grade/edit/tree/item.php?id='.$id.'&amp;courseid='.$courseid;
+        redirect($gpr->add_url_params($url));
+    }
+    $item = $grade_item->get_record_data();
+
+    $parent_category = $grade_item->get_parent_category();
+    $item->parentcategory = $parent_category->id;
+
+    if ($item->itemtype == 'mod') {
+        $cm = get_coursemodule_from_instance($item->itemmodule, $item->iteminstance, $item->courseid);
+        $item->cmid = $cm->id;
+    } else {
+        $item->cmid = 0;
+    }
+
+} else {
+    $grade_item = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual'), false);
+    $item = $grade_item->get_record_data();
+    $item->cmid = 0;
+    $parent_category = grade_category::fetch_course_category($courseid);
+    $item->parentcategory = $parent_category->id;
+}
+
+$decimalpoints = $grade_item->get_decimals();
+
+if ($item->hidden > 1) {
+    $item->hiddenuntil = $item->hidden;
+    $item->hidden = 0;
+} else {
+    $item->hiddenuntil = 0;
+}
+
+$item->locked = !empty($item->locked);
+
+$item->gradepass       = format_float($item->gradepass, $decimalpoints);
+
+if (empty($parent_category)) {
+    $item->aggregationcoef = 0;
+} else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+    $item->aggregationcoef = $item->aggregationcoef > 0 ? 1 : 0;
+} else {
+    $item->aggregationcoef = format_float($item->aggregationcoef, 4);
+}
+
+$mform->set_data($item);
+
+
+if ($data = $mform->get_data(false)) {
+
+    if (!isset($data->aggregationcoef)) {
+        $data->aggregationcoef = 0;
+    }
+
+    if (array_key_exists('calculation', $data)) {
+        $data->calculation = grade_item::normalize_formula($data->calculation, $course->id);
+    }
+
+    $hidden      = empty($data->hidden) ? 0: $data->hidden;
+    $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
+    unset($data->hidden);
+    unset($data->hiddenuntil);
+
+    $locked   = empty($data->locked) ? 0: $data->locked;
+    $locktime = empty($data->locktime) ? 0: $data->locktime;
+    unset($data->locked);
+    unset($data->locktime);
+
+    $convert = array('gradepass', 'aggregationcoef');
+    foreach ($convert as $param) {
+        if (array_key_exists($param, $data)) {
+            $data->$param = unformat_float($data->$param);
+        }
+    }
+
+    $grade_item = new grade_item(array('id'=>$id, 'courseid'=>$courseid));
+    grade_item::set_properties($grade_item, $data);
+
+    // fix activity links
+    if (empty($data->cmid)) {
+        // manual item
+        $grade_item->itemtype     = 'manual';
+        $grade_item->itemmodule   = null;
+        $grade_item->iteminstance = null;
+        $grade_item->itemnumber   = 0;
+
+    } else {
+        $module = get_record_sql("SELECT cm.*, m.name as modname
+                                    FROM {$CFG->prefix}modules m, {$CFG->prefix}course_modules cm
+                                   WHERE cm.id = {$data->cmid} AND cm.module = m.id ");
+        $grade_item->itemtype     = 'mod';
+        $grade_item->itemmodule   = $module->modname;
+        $grade_item->iteminstance = $module->instance;
+
+        if ($items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$grade_item->itemmodule,
+                                           'iteminstance'=>$grade_item->iteminstance, 'courseid'=>$COURSE->id))) {
+            if (!empty($grade_item->id) and in_array($grade_item, $items)) {
+                //no change needed
+            } else {
+                $max = 999;
+                foreach($items as $item) {
+                    if (empty($item->outcomeid)) {
+                        continue;
+                    }
+                    if ($item->itemnumber > $max) {
+                        $max = $item->itemnumber;
+                    }
+                }
+                $grade_item->itemnumber = $max + 1;
+            }
+        } else {
+            $grade_item->itemnumber = 1000;
+        }
+    }
+
+    // fix scale used
+    $outcome = grade_outcome::fetch(array('id'=>$data->outcomeid));
+    $grade_item->gradetype = GRADE_TYPE_SCALE;
+    $grade_item->scaleid = $outcome->scaleid; //TODO: we might recalculate existing outcome grades when changing scale
+
+    if (empty($grade_item->id)) {
+        $grade_item->insert();
+        // move next to activity if adding linked outcome
+        if ($grade_item->itemtype == 'mod') {
+            if ($item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$grade_item->itemmodule,
+                         'iteminstance'=>$grade_item->iteminstance, 'itemnumber'=>0, 'courseid'=>$COURSE->id))) {
+                $grade_item->set_parent($item->categoryid);
+                $grade_item->move_after_sortorder($item->sortorder);
+            }
+        } else {
+            // set parent if needed
+            if (isset($data->parentcategory)) {
+                $grade_item->set_parent($data->parentcategory, 'gradebook');
+            }
+        }
+
+    } else {
+        $grade_item->update();
+    }
+
+    // update hiding flag
+    if ($hiddenuntil) {
+        $grade_item->set_hidden($hiddenuntil, false);
+    } else {
+        $grade_item->set_hidden($hidden, false);
+    }
+
+    $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking
+    $grade_item->set_locked($locked, false, true);
+
+    redirect($returnurl);
+}
+
+$strgrades       = get_string('grades');
+$strgraderreport = get_string('graderreport', 'grades');
+$stroutcomesedit = get_string('outcomeitemsedit', 'grades');
+$stroutcome      = get_string('outcomeitem', 'grades');
+
+$navigation = grade_build_nav(__FILE__, $stroutcome, array('courseid' => $courseid));
+
+print_header_simple($strgrades . ': ' . $strgraderreport, ': ' . $stroutcomesedit, $navigation, '', '', true, '', navmenu($course));
+
+$mform->display();
+
+print_footer($course);
Index: grade/report/simple_grader/version.php
===================================================================
RCS file: grade/report/simple_grader/version.php
diff -N grade/report/simple_grader/version.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/version.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,29 @@
+<?PHP // $Id: version.php,v 1.9 2007-10-10 16:09:42 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$plugin->version  = 2008041800;
+$plugin->requires = 2007101000;
+
+?>
Index: grade/export/csv/index.php
===================================================================
RCS file: grade/export/csv/index.php
diff -N grade/export/csv/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,75 @@
+<?php  //$Id: index.php,v 1.31.2.1 2007-12-07 01:40:45 toyomoyo Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once 'csvlib.php';
+require_once 'grade_export_csv.php';
+
+$id = required_param('id', PARAM_INT); // course id
+
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $id);
+
+require_capability('moodle/grade:export', $context);
+require_capability('gradeexport/csv:view', $context);
+
+
+$strgrades = get_string('grades', 'grades');
+$actionstr = get_string('modulename', 'gradeexport_csv');
+$navigation = grade_build_nav(__FILE__, $actionstr, array('courseid' => $course->id));
+
+print_header($course->shortname.': '.get_string('grades'), $course->fullname, $navigation);
+print_grade_plugin_selector($id, 'export', 'csv');
+
+if (!empty($CFG->gradepublishing)) {
+    $CFG->gradepublishing = has_capability('gradeexport/csv:publish', $context);
+}
+
+$mform = new grade_export_form(null, array('includeseparator'=>false, 'publishing' => true));
+
+// process post information
+if ($data = $mform->get_data()) {
+    $export = new grade_export_csv($course, groups_get_course_group($course), '', false, false, $data->display, $data->decimals);
+
+    // print the grades on screen for feedback
+
+    $export->process_form($data);
+    $export->print_continue();
+    $export->display_preview();
+    print_footer($course);
+    exit;
+}
+
+groups_print_course_menu($course, 'index.php?id='.$id);
+echo '<div class="clearer"></div>';
+
+$mform->display();
+
+print_footer();
+?>
Index: grade/export/csv/db/access.php
===================================================================
RCS file: grade/export/csv/db/access.php
diff -N grade/export/csv/db/access.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/db/access.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,50 @@
+<?php  // $Id: access.php,v 1.3 2007-10-10 06:34:20 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$gradeexport_csv_capabilities = array(
+
+    'gradeexport/csv:view' => array(
+        'riskbitmask' => RISK_PERSONAL,
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    ),
+
+    'gradeexport/csv:publish' => array(
+        'riskbitmask' => RISK_PERSONAL,
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'admin' => CAP_ALLOW
+        )
+    )
+
+);
+
+?>
Index: grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregation.html
===================================================================
RCS file: grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregation.html
diff -N grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregation.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/lang/en_utf8/help/grade/simple_aggregation.html	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,35 @@
+<h1>Category aggregation</h1>
+<p>This menu lets you choose the aggregation strategy that will be used to calculate
+each participant's overall grade for this category. The different options are explained below.</p>
+
+<p>The grades are first converted to percentage values (interval from 0 to 1, this is called normalisation), then aggregated using one of
+the functions below and finally converted to the associated category item's range (between <em>Minimum grade</em> and <em>Maximum grade</em>).</p>
+
+<p><strong>Important</strong>: An empty grade is simply a missing gradebook entry, and could
+mean different things. For example, it could be a participant who hasn't yet submitted an assignment,
+an assignment submission not yet graded by the teacher, or a grade that has been manually deleted by
+the gradebook administrator. Caution in interpreting these "empty grades" is thus advised.</p>
+
+<dl id="grade-aggregation-help">
+    <dt>Weighted mean</dt>
+        <dd>Each grade item can be given a weight, which is then used in the arithmetic mean aggregation to influence
+                         the importance of each item in the overall mean.</dd>
+	<dd>Each grade within a category (or a category total within a parent) is normalized to a decimal value based on the quotient between the points earned and the maximum ensuring that weights are calculated appropriately.</dd>  
+        <dd class="example">A1 70/100 weight 10, A2 20/80 weight 5, A3
+                         10/10 weight 3, category max 100:<br /><code>(0.7*10 + 0.25*5 + 1.0*3)/18 = 0.625 --> 62.5/100</code></dd>
+    
+    <dt>Simple weighted mean</dt>
+        <dd>The difference from <em>Weighted mean</em> is that weight is calculated as <em>Maximum grade</em> - <em>Minimum grade</em>
+                         for each item. 100 point assignment has weight 100, 10 point assignment has weight 10.</dd>
+	<dd>This is the mean that most instructors are used to.</dd>    
+        <dd class="example">A1 70/100, A2 20/80, A3 10/10, category max 100:<br />
+                         <code>(0.7*100 + 0.25*80 + 1.0*10)/190 = 0.526 --> 52.6/100</code></dd>
+    
+    <dt>Sum of grades</dt>
+        <dd>The sum of all grade values. Scale grades are ignored. This is the only type that does not convert the
+                         grades to percentages internally (normalisation). The <em>Maximum grade</em> of associated category item is calculated
+                         automatically as a sum of maximums from all aggregated items.</dd>
+	<dd>Keep highest and drop lowest values are not calculated using this aggregation method</dd>
+        <dd class="example">A1 70/100, A2 20/80, A3 10/10:<br />
+                         <code>70 + 20 + 10 = 100/190</code></dd>
+</dl>   
Index: grade/export/csv/version.php
===================================================================
RCS file: grade/export/csv/version.php
diff -N grade/export/csv/version.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/version.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,29 @@
+<?PHP // $Id: version.php,v 1.6 2007-10-10 16:09:24 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$plugin->version  = 2008062610;
+$plugin->requires = 2007092700;
+
+?>
Index: grade/edit/custom_letter/README.txt
===================================================================
RCS file: grade/edit/custom_letter/README.txt
diff -N grade/edit/custom_letter/README.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/README.txt	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,5 @@
+Copy everything into /grade/edit/custom_letter/ and add the following code just before the </head> tag in header.html
+
+
+    <?php $filenamejs = "$CFG->dirroot/grade/edit/custom_letter/lettermenufixer.php";
+    if (file_exists($filenamejs)) { include($filenamejs); } else { } ?>
Index: blocks/anonymous_grade/enable.php
===================================================================
RCS file: blocks/anonymous_grade/enable.php
diff -N blocks/anonymous_grade/enable.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/enable.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,91 @@
+<?php // $Id: enable.php,v 1.0 2008/05/14 09:53:43 pcali1 Exp $
+
+require_once('../../config.php');
+require_once('enable_form.php');
+
+/**
+ * Author: Philip Cali
+ * The processor for a moodle form that the enables the extra grade features
+ */
+
+require_login();
+
+//User must be admin
+if (!is_siteadmin($USER->id)) {
+    error('You do not have the correct permission to use this block.');
+}
+
+$form = new enable_form();
+$heading = null;
+
+if ($form->is_cancelled()) {
+    redirect($CFG->wwwroot);
+} 
+
+if ($data = $form->get_data()) {
+    if(empty($data->enable_features)) {
+        $data->enable_features = 0;
+    }
+
+    $config = array(
+                'enable_features' => $data->enable_features,
+                'profileid' => (isset($data->profileid)) ? $data->profileid : 0,
+                'extra_credit' => (isset($data->extra_credit)) ? $data->extra_credit : 0,
+                'limit_category' => (isset($data->limit_category)) ? $data->limit_category : 0,
+                'max_adjust_value' => (isset($data->max_adjust_value)) ? format_float($data->max_adjust_value, 2) : 0
+                );
+    insert_config_data($config);
+    $heading = get_string('changessaved');
+} else if(!$form->is_submitted()){
+    $form->set_data(get_config_data());
+}
+
+$blockname = get_string('blockname', 'block_anonymous_grade');
+$navigation = array(
+              array('name' => $blockname, 'link'=>'', 'type'=>'title')
+              );
+
+print_header_simple('', '', build_navigation($navigation));
+
+if (!is_null($heading)) {
+    print_heading($heading);
+}
+
+
+//body here
+$form->display();
+
+print_footer();
+
+//Simple function that either inserts or updates records in the anonymous block config table
+function insert_config_data($config) {
+    foreach ($config as $name => $value) {
+        if ($field = get_record('block_anonymous_grade_config', 'name', $name)) {
+            if ($field->value == $value){
+                continue;
+            }
+            $field->value = $value;
+            update_record('block_anonymous_grade_config', $field);
+            continue;
+        } 
+        $field = new stdClass;
+        $field->name = $name;
+        $field->value = $value;
+        insert_record('block_anonymous_grade_config', $field);
+    }
+}
+
+//Simple function that returns a config object the moodle form will then use to fill
+//pre-existing data
+function get_config_data() {
+    $fields = get_records('block_anonymous_grade_config');
+    $data = array();
+    if ($fields){
+        foreach ($fields as $field){
+            $data[$field->name] = $field->value;
+        }
+    }
+    return $data;
+}
+
+?>
Index: blocks/anonymous_grade/db/upgrade.php
===================================================================
RCS file: blocks/anonymous_grade/db/upgrade.php
diff -N blocks/anonymous_grade/db/upgrade.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/db/upgrade.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,24 @@
+<?php // $Id: block_anonymous_grade.php,v 2.5 2008/09/17 09:53:43 pcali1 Exp $   
+
+/**
+ * Author: Philip Cali
+ * Update the current grades in the system to use the new gradebook
+ * rawgrade/curving system.
+ */
+
+function xmldb_block_anonymous_grade_upgrade($oldversion = 0) {
+	global $CFG;
+
+	$result = true;
+
+	if ($result && $oldversion < 2008091711) {
+		$sql = "UPDATE {$CFG->prefix}grade_grades 
+			SET rawgrade = finalgrade WHERE rawgrade IS NULL
+			AND finalgrade IS NOT NULL";
+		
+        $result = execute_sql($sql);
+		return $result;
+	}
+}
+
+?>
Index: grade/report/simple_grader/lib/menufixer.php
===================================================================
RCS file: grade/report/simple_grader/lib/menufixer.php
diff -N grade/report/simple_grader/lib/menufixer.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lib/menufixer.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,33 @@
+<script type="text/javascript">
+//<![CDATA[
+function ReplaceObj(orig_text, replace_text) {
+    this.replacement = replace_text;
+    this.original = orig_text;
+}
+
+ReplaceObj.prototype.doReplace = function (originalString){
+    return originalString.replace(this.original, this.replacement);
+}
+
+function replace_plugin(){
+	var selector = document.getElementById('choosepluginreport_jump');
+
+	if(selector !=null) {
+        var search_values = new Array(
+                            new ReplaceObj('edit/tree', 'edit/simple_tree'),
+                            new ReplaceObj('edit/letter', 'edit/custom_letter'));
+        
+	    for (var i =0; i< selector.options.length; i++){
+                for (var j=0; j<search_values.length; j++){
+                var replaceObj = search_values[j];
+            
+    			if(selector.options[i].value.search(replaceObj.original)) {
+	    		    selector.options[i].value = replaceObj.doReplace(selector.options[i].value);
+    		    }
+            }
+		}
+	}
+}
+
+//]]>
+</script>
Index: grade/report/simple_grader/db/access.php
===================================================================
RCS file: grade/report/simple_grader/db/access.php
diff -N grade/report/simple_grader/db/access.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/db/access.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,41 @@
+<?php  // $Id: access.php,v 1.5 2008-05-10 06:34:23 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+
+$gradereport_simple_grader_capabilities = array(
+
+    'gradereport/simple_grader:view' => array(
+        'riskbitmask' => RISK_PERSONAL,
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    )
+);
+
+?>
Index: grade/report/simple_grader/tabs.php
===================================================================
RCS file: grade/report/simple_grader/tabs.php
diff -N grade/report/simple_grader/tabs.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/tabs.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,48 @@
+<?php  // $Id: tabs.php,v 1.12 2008-05-08 06:34:21 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ * Date: 05/08/2008
+ * Changed the base base url to point to simple grader's index
+ */
+    $row = $tabs = array();
+    $tabcontext = get_context_instance(CONTEXT_COURSE, $COURSE->id);
+    $row[] = new tabobject('simple_graderreport',
+                           $CFG->wwwroot.'/grade/report/simple_grader/index.php?id='.$courseid,
+                           get_string('modulename', 'gradereport_simple_grader'));
+    if (has_capability('moodle/grade:manage',$tabcontext ) ||
+        has_capability('moodle/grade:edit', $tabcontext) ||
+        has_capability('gradereport/simple_grader:view', $tabcontext)) {
+        $row[] = new tabobject('preferences',
+                               $CFG->wwwroot.'/grade/report/simple_grader/preferences.php?id='.$courseid,
+                               get_string('myreportpreferences', 'grades'));
+    }
+
+    $tabs[] = $row;
+    echo '<div class="gradedisplay">';
+    print_tabs($tabs, $currenttab);
+    echo '</div>';
+?>
Index: grade/edit/simple_tree/item.php
===================================================================
RCS file: grade/edit/simple_tree/item.php
diff -N grade/edit/simple_tree/item.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/item.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,226 @@
+<?php  //$Id: item.php,v 1.14.2.4 2008-05-08 21:19:09 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ */
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/lib.php';
+require_once $CFG->dirroot.'/grade/report/simple_grader/lib/simple_grade_hook.php';
+require_once 'item_form.php';
+
+$courseid = required_param('courseid', PARAM_INT);
+$id       = optional_param('id', 0, PARAM_INT);
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+require_capability('moodle/grade:manage', $context);
+
+// default return url
+$gpr = new grade_plugin_return();
+$returnurl = $gpr->get_return_url('index.php?id='.$course->id);
+
+$mform = new edit_item_form(null, array('gpr'=>$gpr));
+
+if ($mform->is_cancelled()) {
+    redirect($returnurl);
+}
+
+$params = array('id' => $id, 'courseid'=>$courseid);
+
+if ($grade_item = grade_item::fetch($params)) {
+    // redirect if outcomeid present
+    if (!empty($grade_item->outcomeid) && !empty($CFG->enableoutcomes)) {
+        $url = $CFG->wwwroot.'/grade/edit/simple_tree/outcomeitem.php?id='.$id.'&amp;courseid='.$courseid;
+        redirect($gpr->add_url_params($url));
+    }
+    $item = $grade_item->get_record_data();
+
+    if ($grade_item->is_course_item()) {
+        $parent_category = null;
+        $item->parentcategory = 0;
+    } else if ($grade_item->is_category_item()) {
+        $parent_category = $grade_item->get_parent_category();
+        $parent_category = $parent_category->get_parent_category();
+        $item->parentcategory = $parent_category->id;
+    } else {
+        $parent_category = $grade_item->get_parent_category();
+        $item->parentcategory = $parent_category->id;
+    }
+} else {
+    $grade_item = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual'), false);
+    $item = $grade_item->get_record_data();
+    $parent_category = grade_category::fetch_course_category($courseid);
+    $item->parentcategory = $parent_category->id;
+    $item->aggregationcoef = 1;
+
+}
+    
+// Derive extra credit
+$item->extra_credit = ($item->aggregationcoef == 0) ? 1 : 0;
+$decimalpoints = $grade_item->get_decimals();
+
+if ($item->hidden > 1) {
+    $item->hiddenuntil = $item->hidden;
+    $item->hidden = 0;
+} else {
+    $item->hiddenuntil = 0;
+}
+
+$item->locked = !empty($item->locked);
+
+$item->grademax        = format_float($item->grademax, $decimalpoints);
+$item->grademin        = format_float($item->grademin, $decimalpoints);
+$item->gradepass       = format_float($item->gradepass, $decimalpoints);
+$item->multfactor      = format_float($item->multfactor, 4);
+$item->plusfactor      = format_float($item->plusfactor, 4);
+
+//anonymous
+//we have to check if this particular grade item is flagged anonymous
+if ($grade_item->id and get_field('block_anon_grade_items', 'id', 'itemid', $grade_item->id)){
+    $item->anonymous = 1;
+}
+
+if (empty($parent_category)) {
+    $item->aggregationcoef = 1;
+} else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+    $item->aggregationcoef = $item->aggregationcoef < 1 ? 0 : 1;
+} else {
+    $item->aggregationcoef = format_float($item->aggregationcoef, 4);
+}
+
+$mform->set_data($item);
+
+if ($data = $mform->get_data(false)) {
+
+    if (!isset($data->aggregationcoef)) {
+        $data->aggregationcoef = 1;
+    }
+
+    $hidden      = empty($data->hidden) ? 0: $data->hidden;
+    $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
+    unset($data->hidden);
+    unset($data->hiddenuntil);
+    $data->grademin = 0.0000;
+
+
+    $locked   = empty($data->locked) ? 0: $data->locked;
+    $locktime = empty($data->locktime) ? 0: $data->locktime;
+    unset($data->locked);
+    unset($data->locktime);
+
+    $convert = array('grademax', 'grademin', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef');
+    foreach ($convert as $param) {
+        if (array_key_exists($param, $data)) {
+            $data->$param = unformat_float($data->$param);
+        }
+    }
+
+
+    //Handle the extra credit case
+    if (isset($data->extra_credit)) {        
+        $data->aggregationcoef = 0.0000;
+        unset($data->extra_credit);
+    } else if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN && $data->aggregationcoef == 0) {
+        $data->aggregationcoef = 1.0000;
+    }
+
+    // Tell the grade object api where to pull manually
+    $grade_item = new grade_item(array('id'=>$id, 'courseid'=>$courseid));
+    grade_item::set_properties($grade_item, $data);
+    $grade_item->outcomeid = null;
+
+    // Handle null decimals value
+    if (!array_key_exists('decimals', $data) or $data->decimals < 0) {
+        $grade_item->decimals = null;
+    }
+
+    if (empty($grade_item->id)) {
+        $grade_item->itemtype = 'manual'; // all new items to be manual only
+        $grade_item->insert();
+        
+        //check the anonymous checkbox
+        if ($data->anonymous) {
+            $anon_reference = new stdClass;
+            $anon_reference->itemid = $grade_item->id;
+            $anon_reference->completed = 0;
+            insert_record('block_anon_grade_items', $anon_reference);
+        }
+
+        // set parent if needed
+        if (isset($data->parentcategory)) {
+            $grade_item->set_parent($data->parentcategory, 'gradebook');
+            $parent_category = grade_category::fetch(array('id'=> $data->parentcategory, 'courseid'=>$courseid));
+        }
+
+    } else {
+        $grade_item->update();
+    }
+   
+    // Update the sum max value if necessary         
+    if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+        derive_sum_max($parent_category);
+    }
+
+    // update hiding flag
+    if ($hiddenuntil) {
+        $grade_item->set_hidden($hiddenuntil, false);
+    } else {
+        $grade_item->set_hidden($hidden, false);
+    }
+
+    $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking
+    $grade_item->set_locked($locked, false, true);
+
+
+    // Hardcode the url for now;  we want to go back to the tree when we're done here
+    redirect($returnurl);
+}
+
+$strgrades       = get_string('grades');
+$strgraderreport = get_string('graderreport', 'grades');
+$stritemsedit    = get_string('itemsedit', 'grades');
+$stritem         = get_string('item', 'grades');
+
+$navigation = array(
+              //array('name'=> $course->shortname, 'link'=> "{$CFG->wwwroot}/course/view.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $strgrades, 'link'=>"{$CFG->wwwroot}/grade/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $strgraderreport, 'link'=>"{$CFG->wwwroot}/grade/report/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> 'EDIT', 'link'=>"{$CFG->wwwroot}/grade/edit/simple_tree/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $stritem, 'link' =>'', 'type'=>'title')
+            );
+
+
+print_header_simple($stritem, '', build_navigation($navigation));
+
+$mform->display();
+
+print_footer($course);
Index: grade/export/csv/csvlib.php
===================================================================
RCS file: grade/export/csv/csvlib.php
diff -N grade/export/csv/csvlib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/csvlib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,387 @@
+<?php // $Id: csvlib.php,v 1.45.2.6 2008/03/02 15:15:07 moodler Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once($CFG->dirroot.'/lib/gradelib.php');
+require_once($CFG->dirroot.'/grade/lib.php');
+require_once($CFG->dirroot.'/grade/export/grade_export_form.php');
+
+/**
+ * Base export class
+ */
+class grade_export {
+
+    var $plugin; // plgin name - must be filled in subclasses!
+
+    var $grade_items; // list of all course grade items
+    var $groupid;     // groupid, 0 means all groups
+    var $course;      // course object
+    var $columns;     // array of grade_items selected for export
+
+    var $previewrows;     // number of rows in preview
+    var $export_letters;  // export letters
+    var $export_feedback; // export feedback
+    var $userkey;         // export using private user key
+
+    var $updatedgradesonly; // only export updated grades
+    var $displaytype; // display type (e.g. real, percentages, letter) for exports
+    var $decimalpoints; // number of decimal points for exports
+    /**
+     * Constructor should set up all the private variables ready to be pulled
+     * @param object $course
+     * @param int $groupid id of selected group, 0 means all
+     * @param string $itemlist comma separated list of item ids, empty means all
+     * @param boolean $export_feedback
+     * @param boolean $export_letters
+     * @note Exporting as letters will lead to data loss if that exported set it re-imported.
+     */
+    function grade_export($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2) {
+        $this->course = $course;
+        $this->groupid = $groupid;
+        $this->grade_items = grade_item::fetch_all(array('courseid'=>$this->course->id));
+
+        $this->columns = array();
+        if (!empty($itemlist)) {
+            $itemids = explode(',', $itemlist);
+            // remove items that are not requested
+            foreach ($itemids as $itemid) {
+                if (array_key_exists($itemid, $this->grade_items)) {
+                    $this->columns[$itemid] =& $this->grade_items[$itemid];
+                }
+            }
+        } else {
+            foreach ($this->grade_items as $itemid=>$unused) {
+                $this->columns[$itemid] =& $this->grade_items[$itemid];
+            }
+        }
+
+        $this->export_feedback = $export_feedback;
+        $this->userkey         = '';
+        $this->previewrows     = false;
+        $this->updatedgradesonly = $updatedgradesonly;
+        
+        $this->displaytype = $displaytype;
+        $this->decimalpoints = $decimalpoints;
+    }
+
+    /**
+     * Init object based using data from form
+     * @param object $formdata
+     */
+    function process_form($formdata) {
+        global $USER;
+
+        $this->columns = array();
+        if (!empty($formdata->itemids)) {
+            foreach ($formdata->itemids as $itemid=>$selected) {
+                if ($selected and array_key_exists($itemid, $this->grade_items)) {
+                    $this->columns[$itemid] =& $this->grade_items[$itemid];
+                }
+            }
+        } else {
+            foreach ($this->grade_items as $itemid=>$unused) {
+                $this->columns[$itemid] =& $this->grade_items[$itemid];
+            }
+        }
+
+        if (isset($formdata->key)) {
+            if ($formdata->key == 1 && isset($formdata->iprestriction) && isset($formdata->validuntil)) {
+                // Create a new key
+                $formdata->key = create_user_key('grade/export', $USER->id, $this->course->id, $formdata->iprestriction, $formdata->validuntil);
+            }
+            $this->userkey = $formdata->key;
+        }
+
+        if (isset($formdata->export_letters)) {
+            $this->export_letters = $formdata->export_letters;
+        }
+
+        if (isset($formdata->export_feedback)) {
+            $this->export_feedback = $formdata->export_feedback;
+        }
+
+        if (isset($formdata->previewrows)) {
+            $this->previewrows = $formdata->previewrows;
+        }
+
+    }
+
+    /**
+     * Update exported field in grade_grades table
+     * @return boolean
+     */
+    function track_exports() {
+        global $CFG;
+
+        /// Whether this plugin is entitled to update export time
+        if ($expplugins = explode(",", $CFG->gradeexport)) {
+            if (in_array($this->plugin, $expplugins)) {
+                return true;
+            } else {
+                return false;
+          }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns string representation of final grade
+     * @param $object $grade instance of grade_grade class
+     * @return string
+     */
+    function format_grade($grade) {
+        return grade_format_gradevalue($grade->finalgrade, $this->grade_items[$grade->itemid], false, $this->displaytype, $this->decimalpoints);
+    }
+
+    /**
+     * Returns the name of column in export
+     * @param object $grade_item
+     * @param boolena $feedback feedback colum
+     * &return string
+     */
+    function format_column_name($grade_item, $feedback=false) {
+        if ($grade_item->itemtype == 'mod') {
+            $name = get_string('modulename', $grade_item->itemmodule).': '.$grade_item->get_name();
+        } else {
+            $name = $grade_item->get_name();
+        }
+
+        if ($feedback) {
+            $name .= ' ('.get_string('feedback').')';
+        }
+
+        return strip_tags($name);
+    }
+
+    /**
+     * Returns formatted grade feedback
+     * @param object $feedback object with properties feedback and feedbackformat
+     * @return string
+     */
+    function format_feedback($feedback) {
+        return strip_tags(format_text($feedback->feedback, $feedback->feedbackformat));
+    }
+
+    /**
+     * Implemented by child class
+     */
+    function print_grades() { }
+
+    /**
+     * Prints preview of exported grades on screen as a feedback mechanism
+     */
+    function display_preview() {
+
+        print_heading(get_string('previewrows', 'grades'));
+
+        echo '<table class="csvgradetable">';
+        echo '<tr>';
+        echo '<th>'.get_string("idnumber")."</th>".
+             '<th>'.get_string("lastname")."</th>".
+             '<th>'.get_string("firstname")."</th>".
+             '<th>'.get_string("email")."</th>";
+        foreach ($this->columns as $grade_item) {
+            echo '<th>'.$this->format_column_name($grade_item).'</th>';
+
+            /// add a column_feedback column
+            if ($this->export_feedback) {
+                echo '<th>'.$this->format_column_name($grade_item, true).'</th>';
+            }
+        }
+        echo '</tr>';
+        /// Print all the lines of data.
+
+        $i = 0;
+        $gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
+        $gui->init();
+        while ($userdata = $gui->next_user()) {
+            // number of preview rows
+            if ($this->previewrows and $this->previewrows <= $i) {
+                break;
+            }
+            $user = $userdata->user;
+            // if (empty($user->idnumber)) {   // Not sure why this was here, ccommented out for MDL-13722
+            //     continue;
+            // }
+            
+            $gradeupdated = false; // if no grade is update at all for this user, do not display this row
+            $rowstr = '';
+            foreach ($this->columns as $itemid=>$unused) {
+                $gradetxt = $this->format_grade($userdata->grades[$itemid]);
+                
+                // get the status of this grade, and put it through track to get the status
+                $g = new grade_export_update_buffer();
+                $grade_grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$user->id));
+                $status = $g->track($grade_grade);
+
+                if ($this->updatedgradesonly && ($status == 'nochange' || $status == 'unknown')) {
+                    $rowstr .= '<td>'.get_string('unchangedgrade', 'grades').'</td>';
+                } else {
+                    $rowstr .= "<td>$gradetxt</td>";
+                    $gradeupdated = true;
+                }
+                
+                if ($this->export_feedback) {
+                    $rowstr .=  '<td>'.$this->format_feedback($userdata->feedbacks[$itemid]).'</td>';
+                }
+            }
+
+            // if we are requesting updated grades only, we are not interested in this user at all            
+            if (!$gradeupdated && $this->updatedgradesonly) {
+                continue; 
+            }
+
+            echo '<tr>';
+            echo "<td>$user->idnumber</td><td>$user->lastname</td><td>$user->firstname</td><td>$user->email</td>";           
+            echo $rowstr;
+            echo "</tr>";
+            
+            $i++; // increment the counter
+        }
+        echo '</table>';
+        $gui->close();
+    }
+
+    /**
+     * Returns array of parameters used by dump.php and export.php.
+     * @return array
+     */
+    function get_export_params() {
+        $itemids = array_keys($this->columns);
+
+        $params = array('id'                =>$this->course->id,
+                        'groupid'           =>$this->groupid,
+                        'itemids'           =>implode(',', $itemids),
+                        'export_letters'    =>$this->export_letters,
+                        'export_feedback'   =>$this->export_feedback,
+                        'updatedgradesonly' =>$this->updatedgradesonly,
+                        'displaytype'       =>$this->displaytype,
+                        'decimalpoints'     =>$this->decimalpoints);
+
+        return $params;
+    }
+
+    /**
+     * Either prints a "Export" box, which will redirect the user to the download page,
+     * or prints the URL for the published data.
+     * @return void
+     */
+    function print_continue() {
+        global $CFG;
+
+        $params = $this->get_export_params();
+
+
+        print_heading(get_string('export', 'grades'));
+
+        echo '<div class="gradeexportlink">';
+        if (!$this->userkey) {      // this button should trigger a download prompt
+            print_single_button($CFG->wwwroot.'/grade/export/'.$this->plugin.'/export.php',
+                                $params, get_string('download', 'admin'));
+
+        } else {
+            $paramstr = '';
+            $sep = '?';
+            foreach($params as $name=>$value) {
+                $paramstr .= $sep.$name.'='.$value;
+                $sep = '&amp;';
+            }
+
+            $link = $CFG->wwwroot.'/grade/export/'.$this->plugin.'/dump.php'.$paramstr.'&amp;key='.$this->userkey;
+
+            echo get_string('download', 'admin').': <a href="'.$link.'">'.$link.'</a>';
+        }
+        echo '</div>';
+    }
+}
+
+/**
+ * This class is used to update the exported field in grade_grades.
+ * It does internal buffering to speedup the db operations.
+ */
+class grade_export_update_buffer {
+    var $update_list;
+    var $export_time;
+
+    /**
+     * Constructor - creates the buffer and initialises the time stamp
+     */
+    function grade_export_update_buffer() {
+        $this->update_list = array();
+        $this->export_time = time();
+    }
+
+    function flush($buffersize) {
+        global $CFG;
+
+        if (count($this->update_list) > $buffersize) {
+            $list = implode(',', $this->update_list);
+            $sql = "UPDATE {$CFG->prefix}grade_grades SET exported = {$this->export_time} WHERE id IN ($list)";
+            execute_sql($sql, false);
+            $this->update_list = array();
+        }
+    }
+
+    /**
+     * Track grade export status
+     * @param object $grade_grade
+     * @return string $status (unknow, new, regrade, nochange)
+     */
+    function track($grade_grade) {
+
+        if (empty($grade_grade->exported) or empty($grade_grade->timemodified)) {
+            if (is_null($grade_grade->finalgrade)) {
+                // grade does not exist yet
+                $status = 'unknown';
+            } else {
+                $status = 'new';
+                $this->update_list[] = $grade_grade->id;
+            }
+
+        } else if ($grade_grade->exported < $grade_grade->timemodified) {
+            $status = 'regrade';
+            $this->update_list[] = $grade_grade->id;
+
+        } else if ($grade_grade->exported >= $grade_grade->timemodified) {
+            $status = 'nochange';
+
+        } else {
+            // something is wrong?
+            $status = 'unknown';
+        }
+
+        $this->flush(100);
+
+        return $status;
+    }
+
+    /**
+     * Flush and close the buffer.
+     */
+    function close() {
+        $this->flush(0);
+    }
+}
+?>
Index: grade/export/csv/export.php
===================================================================
RCS file: grade/export/csv/export.php
diff -N grade/export/csv/export.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/export.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,54 @@
+<?php  //$Id: export.php,v 1.9 2007-10-10 06:43:24 toyomoyo Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once 'csvlib.php';
+require_once 'grade_export_csv.php';
+
+$id                = required_param('id', PARAM_INT); // course id
+$groupid           = optional_param('groupid', 0, PARAM_INT);
+$itemids           = required_param('itemids', PARAM_RAW);
+$export_feedback   = optional_param('export_feedback', 0, PARAM_BOOL);
+$separator         = optional_param('separator', 'comma', PARAM_ALPHA);
+$updatedgradesonly = optional_param('updatedgradesonly', false, PARAM_BOOL);
+$displaytype       = optional_param('displaytype', $CFG->grade_export_displaytype, PARAM_INT);
+$decimalpoints     = optional_param('decimalpoints', $CFG->grade_export_decimalpoints, PARAM_INT);
+
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $id);
+
+require_capability('moodle/grade:export', $context);
+require_capability('gradeexport/csv:view', $context);
+
+
+// print all the exported data here
+$export = new grade_export_csv($course, $groupid, $itemids, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints, $separator);
+$export->print_grades();
+
+?>
Index: grade/report/projected/db/access.php
===================================================================
RCS file: grade/report/projected/db/access.php
diff -N grade/report/projected/db/access.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/db/access.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,41 @@
+<?php  // $Id: access.php,v 1.5 2007-10-10 06:34:23 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$gradereport_projected_capabilities = array(
+
+    'gradereport/projected:view' => array(
+        'riskbitmask' => RISK_PERSONAL,
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'student' => CAP_ALLOW,
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    ),
+);
+
+?>
Index: grade/import/mymathlab/gradeimport_mymathlab.php
===================================================================
RCS file: grade/import/mymathlab/gradeimport_mymathlab.php
diff -N grade/import/mymathlab/gradeimport_mymathlab.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/gradeimport_mymathlab.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,25 @@
+<?php
+
+// General Strings
+$string['modulename'] = 'MyMathLab File Importer';
+
+// Upload Form Strings (index.php)
+$string['file'] = 'MyMathLab File';
+$string['upload'] = 'Upload File';
+
+// Mapping Form Strings (mapping.php)
+$string['math_grades_header'] = 'MyMathLab Grades';
+$string['moodle_grades_header'] = 'Moodle Grades';
+$string['map_to'] = 'should be mapped to';
+$string['map_grades'] = 'Map Grades';
+$string['select_item'] = 'Please select a grade item';
+$string['converted'] = 'Your grades were converted to percents';
+$string['skip'] = 'is not enrolled in this course and was skipped';
+$string['file_error'] = 'An error has occurred with your file.';
+$string['validation_error'] = 'No valid grade items were found in your file. ' .
+                              'Please check that the file is correct.';
+
+// Import Page Strings (import.php)
+$string['success'] = 'grade items were successfully imported';
+
+?>
Index: grade/edit/simple_tree/item_form.php
===================================================================
RCS file: grade/edit/simple_tree/item_form.php
diff -N grade/edit/simple_tree/item_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/item_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,405 @@
+<?php  //$Id: item_form.php,v 1.20.2.18 2008-05-08 21:25:39 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ */ 
+
+require_once $CFG->libdir.'/formslib.php';
+
+class edit_item_form extends moodleform {
+    var $displayoptions;
+
+    function definition() {
+        global $COURSE, $CFG, $USER;
+
+        $mform =& $this->_form;
+
+/// visible elements
+        $mform->addElement('header', 'general', get_string('gradeitem', 'grades'));
+
+        $mform->addElement('text', 'itemname', get_string('itemname', 'grades'));
+
+        $mform->addElement('checkbox', 'anonymous', ' Anonymous Grade Item', '');
+        $mform->setHelpButton('anonymous', array('anonymous', 'anonymous', 'grade'), true);    
+
+        $mform->addElement('text', 'iteminfo', get_string('iteminfo', 'grades'));
+        $mform->setHelpButton('iteminfo', array('iteminfo', get_string('iteminfo', 'grades'), 'grade'), true);
+
+        $mform->addElement('text', 'idnumber', get_string('idnumbermod'));
+        $mform->setHelpButton('idnumber', array('idnumber', get_string('idnumber', 'grades'), 'grade'), true);
+
+        $options = array(GRADE_TYPE_NONE=>get_string('typenone', 'grades'),
+                         GRADE_TYPE_VALUE=>get_string('typevalue', 'grades'),
+                         GRADE_TYPE_SCALE=>get_string('typescale', 'grades'),
+                         GRADE_TYPE_TEXT=>get_string('typetext', 'grades'));
+
+        $mform->addElement('select', 'gradetype', get_string('gradetype', 'grades'), $options);
+        $mform->setHelpButton('gradetype', array('gradetype', get_string('gradetype', 'grades'), 'grade'), true);
+        $mform->setDefault('gradetype', GRADE_TYPE_VALUE);
+
+        //$mform->addElement('text', 'calculation', get_string('calculation', 'grades'));
+        //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_TEXT);
+        //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_NONE);
+
+        $options = array(0=>get_string('usenoscale', 'grades'));
+        if ($scales = get_records_sql("SELECT * FROM {$CFG->prefix}scale where courseid in({$COURSE->id}, 0) or userid={$USER->id}")) {
+            foreach ($scales as $scale) {
+                $options[$scale->id] = format_string($scale->name);
+            }
+        }
+        $mform->addElement('select', 'scaleid', get_string('scale'), $options);
+        $mform->setHelpButton('scaleid', array('scaleid', get_string('scaleid', 'grades'), 'grade'), true);
+        $mform->disabledIf('scaleid', 'gradetype', 'noteq', GRADE_TYPE_SCALE);
+
+        $mform->addElement('text', 'grademax', get_string('grademax', 'grades'));
+        $mform->setHelpButton('grademax', array('grademax', get_string('grademax', 'grades'), 'grade'), true);
+        $mform->disabledIf('grademax', 'gradetype', 'noteq', GRADE_TYPE_VALUE);
+
+        //Removed to make the aggregation method useful to humans, after all, we're not all math professors.
+	//$mform->addElement('text', 'grademin', get_string('grademin', 'grades'));
+        $mform->setHelpButton('grademin', array('grademin', get_string('grademin', 'grades'), 'grade'), true);
+        $mform->disabledIf('grademin', 'gradetype', 'noteq', GRADE_TYPE_VALUE);
+
+        $mform->addElement('text', 'gradepass', get_string('gradepass', 'grades'));
+        $mform->setHelpButton('gradepass', array('gradepass', get_string('gradepass', 'grades'), 'grade'), true);
+        $mform->disabledIf('gradepass', 'gradetype', 'eq', GRADE_TYPE_NONE);
+        $mform->disabledIf('gradepass', 'gradetype', 'eq', GRADE_TYPE_TEXT);
+
+        $mform->addElement('text', 'multfactor', get_string('multfactor', 'grades'));
+        $mform->setHelpButton('multfactor', array('multfactor', get_string('multfactor', 'grades'), 'grade'), true);
+        $mform->setAdvanced('multfactor');
+        $mform->disabledIf('multfactor', 'gradetype', 'eq', GRADE_TYPE_NONE);
+        $mform->disabledIf('multfactor', 'gradetype', 'eq', GRADE_TYPE_TEXT);
+
+        $mform->addElement('text', 'plusfactor', get_string('plusfactor', 'grades'));
+        $mform->setHelpButton('plusfactor', array('plusfactor', get_string('plusfactor', 'grades'), 'grade'), true);
+        $mform->setAdvanced('plusfactor');
+        $mform->disabledIf('plusfactor', 'gradetype', 'eq', GRADE_TYPE_NONE);
+        $mform->disabledIf('plusfactor', 'gradetype', 'eq', GRADE_TYPE_TEXT);
+
+        /// grade display prefs
+        $default_gradedisplaytype = grade_get_setting($COURSE->id, 'displaytype', $CFG->grade_displaytype);
+        $options = array(GRADE_DISPLAY_TYPE_DEFAULT    => get_string('default', 'grades'),
+                         GRADE_DISPLAY_TYPE_REAL       => get_string('real', 'grades'),
+                         GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'),
+                         GRADE_DISPLAY_TYPE_LETTER     => get_string('letter', 'grades'));
+        foreach ($options as $key=>$option) {
+            if ($key == $default_gradedisplaytype) {
+                $options[GRADE_DISPLAY_TYPE_DEFAULT] = get_string('defaultprev', 'grades', $option);
+                break;
+            }
+        }
+        $mform->addElement('select', 'display', get_string('gradedisplaytype', 'grades'), $options);
+        $mform->setHelpButton('display', array('gradedisplaytype', get_string('gradedisplaytype', 'grades'), 'grade'), true);
+
+        $default_gradedecimals = grade_get_setting($COURSE->id, 'decimalpoints', $CFG->grade_decimalpoints);
+        $options = array(-1=>get_string('defaultprev', 'grades', $default_gradedecimals), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
+        $mform->addElement('select', 'decimals', get_string('decimalpoints', 'grades'), $options);
+        $mform->setHelpButton('decimals', array('decimalpoints', get_string('decimalpoints', 'grades'), 'grade'), true);
+        $mform->setDefault('decimals', -1);
+        $mform->disabledIf('decimals', 'display', 'eq', GRADE_DISPLAY_TYPE_LETTER);
+        if ($default_gradedisplaytype == GRADE_DISPLAY_TYPE_LETTER) {
+            $mform->disabledIf('decimals', 'display', "eq", GRADE_DISPLAY_TYPE_DEFAULT);
+        }
+
+        /// hiding
+        // advcheckbox is not compatible with disabledIf!
+        $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades'));
+        $mform->setHelpButton('hidden', array('hidden', get_string('hidden', 'grades'), 'grade'));
+        $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('hiddenuntil', array('hiddenuntil', get_string('hiddenuntil', 'grades'), 'grade'));
+        $mform->disabledIf('hidden', 'hiddenuntil[off]', 'notchecked');
+
+        /// locking
+        $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades'));
+        $mform->setHelpButton('locked', array('locked', get_string('locked', 'grades'), 'grade'));
+
+        $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('locktime', array('lockedafter', get_string('locktime', 'grades'), 'grade'));
+        $mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE);
+
+/// parent category related settings
+        $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades'));
+
+        $options = array();
+        $default = '';
+        $coefstring = '';
+        $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id));
+        foreach ($categories as $cat) {
+            $cat->apply_forced_settings();
+            $options[$cat->id] = $cat->get_name();
+            if ($cat->is_course_category()) {
+                $default = $cat->id;
+            }
+            if ($cat->is_aggregationcoef_used()) {
+                if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                    $coefstring = 'aggregationcoefweight';
+
+                } else if ($cat->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
+                    $coefstring = 'aggregationcoefextra';
+
+                } else if ($cat->aggregation == GRADE_AGGREGATE_SUM) {
+                    $coefstring = $coefstring=='aggregationcoefextrasum';
+                    $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id);
+                } else {
+                    $coefstring = 'aggregationcoefweight';
+                }
+            } else {
+                $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id);
+            }
+        }
+
+        if (count($categories) > 0) {
+            $mform->addElement('select', 'parentcategory', get_string('gradecategory', 'grades'), $options);
+        }
+
+        $coefstring = 'aggregationcoefweight';
+
+        if ($coefstring !== '') {
+            if ($coefstring == 'aggregationcoefextrasum') {
+                // advcheckbox is not compatible with disabledIf!
+            } else {
+                $mform->addElement('text', 'aggregationcoef', get_string($coefstring, 'grades'));
+            }
+            $mform->addElement('checkbox', 'extra_credit', get_string('aggregationcoefextra', 'grades'));
+            $mform->setHelpButton('extra_credit', array('extra_credit', get_string('aggregationcoefextra', 'grades'), 'grade'), true);
+            $mform->disabledIf('aggregationcoef', 'extra_credit', 'checked');
+            $mform->setHelpButton('aggregationcoef', array($coefstring, get_string($coefstring, 'grades'), 'grade'), true);
+        }
+
+/// hidden params
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'courseid', $COURSE->id);
+        $mform->setType('courseid', PARAM_INT);
+
+        $mform->addElement('hidden', 'itemtype', 'manual'); // all new items are manual only
+        $mform->setType('itemtype', PARAM_ALPHA);
+
+/// add return tracking info
+        $gpr = $this->_customdata['gpr'];
+        $gpr->add_mform_elements($mform);
+
+/// mark advanced according to site settings
+        if (isset($CFG->grade_item_advanced)) {
+            $advanced = explode(',', $CFG->grade_item_advanced);
+            foreach ($advanced as $el) {
+                if ($mform->elementExists($el)) {
+                    $mform->setAdvanced($el);
+                }
+            }
+        }
+//-------------------------------------------------------------------------------
+        // buttons
+        $this->add_action_buttons();
+    }
+
+
+/// tweak the form - depending on existing data
+    function definition_after_data() {
+        global $CFG, $COURSE;
+
+        $mform =& $this->_form;
+        $course = get_record('course', 'id', $COURSE->id);
+
+        $block_data = get_field('block_anonymous_grade_config', 'value', 'name', 'limit_category');
+ 
+        // Check if the block exists
+        $exists = false;
+        if ((isset($block_data) && $block_data == '0') || ($course->category == (int)$block_data)){
+            $exists = true;
+        }
+       
+
+        // Is extra credit enabled? 
+        $extra_enable = 0;
+        if (get_field('block_anonymous_grade_config', 'value', 'name', 'enable_features')) {
+            if (get_field('block_anonymous_grade_config', 'value', 'name', 'profileid')=='0' 
+            || !$exists) {
+                $mform->removeElement('anonymous');
+            }
+            $extra_enable = get_field('block_anonymous_grade_config', 'value', 'name', 'extra_credit');
+        }
+
+        if ($id = $mform->getElementValue('id')) {
+            $grade_item = grade_item::fetch(array('id'=>$id));
+    
+            if ($mform->elementExists('anonymous')) {
+                $mform->removeElement('anonymous');
+            }
+
+            if (!$grade_item->is_raw_used()) {
+                $mform->removeElement('plusfactor');
+                //$mform->removeElement('multfactor');
+            }
+
+            if ($grade_item->is_outcome_item()) {
+                // we have to prevent incompatible modifications of outcomes if outcomes disabled
+                $mform->removeElement('grademax');
+                //$mform->removeElement('grademin');
+                $mform->removeElement('gradetype');
+                $mform->removeElement('display');
+                $mform->removeElement('decimals');
+                $mform->hardFreeze('scaleid');
+
+            } else {
+                if ($grade_item->is_external_item()) {
+                    // following items are set up from modules and should not be overrided by user
+                    $mform->hardFreeze('itemname,idnumber,gradetype,grademax,scaleid');
+                    //$mform->removeElement('calculation');
+                }
+            }
+
+            //remove the aggregation coef element if not needed
+            if ($grade_item->is_course_item()) {
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->removeElement('parentcategory');
+                }
+                if ($mform->elementExists('itemname')) {
+                   $mform->removeElement('itemname');
+                }
+                if ($mform->elementExists('aggregationcoef')) {
+                    $mform->removeElement('aggregationcoef');
+                } 
+                if ($mform->elementExists('extra_credit')) {
+                    $mform->removeElement('extra_credit');
+                } 
+
+            } else {
+                // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!!
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->hardFreeze('parentcategory');
+                }
+
+                if ($grade_item->is_category_item()) {
+                    $category = $grade_item->get_item_category();
+                    $parent_category = $category->get_parent_category();
+                } else {
+                    $parent_category = $grade_item->get_parent_category();
+                }
+
+                $parent_category->apply_forced_settings();
+
+                if (!$parent_category->is_aggregationcoef_used()) {
+                    if ($mform->elementExists('aggregationcoef')) {
+                        $mform->removeElement('aggregationcoef');
+                    }
+                } else {
+                    //fix label if needed
+                    $aggcoef = '';
+                    if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                        $agg_el =& $mform->getElement('aggregationcoef');
+                        $aggcoef = 'aggregationcoefweight';
+                        if (!$extra_enable) {
+                            $mform->removeElement('extra_credit');
+                        }
+                        $agg_el->setLabel(get_string($aggcoef, 'grades'));
+                        $mform->setHelpButton('aggregationcoef', array($aggcoef, get_string($aggcoef, 'grades'), 'grade'), true);
+
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
+                        $aggcoef = 'aggregationcoefextra';
+
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+                        $aggcoef = 'aggregationcoefextrasum';
+                        if ($mform->elementExists('aggregationcoef')) {
+                           $mform->removeElement('aggregationcoef');
+                        } 
+                    }
+                }
+            }
+
+            if ($category = $grade_item->get_item_category()) {
+                if ($category->aggregation == GRADE_AGGREGATE_SUM) {
+                    if ($mform->elementExists('gradetype')) {
+                        $mform->hardFreeze('gradetype');
+                    }
+                    if ($mform->elementExists('grademin')) {
+                        $mform->hardFreeze('grademin');
+                    }
+                    if ($mform->elementExists('grademax')) {
+                        $mform->hardFreeze('grademax');
+                    }
+                    if ($mform->elementExists('scaleid')) {
+                        $mform->removeElement('scaleid');
+                    }
+                }
+            }
+
+        } else {
+            // all new items are manual, children of course category
+            $mform->removeElement('plusfactor');
+            $mform->removeElement('multfactor');
+        }
+
+        // no parent header for course category
+        if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) {
+            $mform->removeElement('headerparent');
+        }
+    }
+
+
+/// perform extra validation before submission
+    function validation($data, $files) {
+        global $COURSE;
+
+        $errors = parent::validation($data, $files);
+
+        if (array_key_exists('idnumber', $data)) {
+            if ($data['id']) {
+                $grade_item = new grade_item(array('id'=>$data['id'], 'courseid'=>$data['courseid']));
+                if ($grade_item->itemtype == 'mod') {
+                    $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid);
+                } else {
+                    $cm = null;
+                }
+            } else {
+                $grade_item = null;
+                $cm = null;
+            }
+            if (!grade_verify_idnumber($data['idnumber'], $COURSE->id, $grade_item, $cm)) {
+                $errors['idnumber'] = get_string('idnumbertaken');
+            }
+        }
+
+        if (array_key_exists('gradetype', $data) and $data['gradetype'] == GRADE_TYPE_SCALE) {
+            if (empty($data['scaleid'])) {
+                $errors['scaleid'] = get_string('missingscale', 'grades');
+            }
+        }
+
+        if (array_key_exists('grademin', $data) and array_key_exists('grademax', $data)) {
+            if ($data['grademax'] == $data['grademin'] or $data['grademax'] < $data['grademin']) {
+                $errors['grademin'] = get_string('incorrectminmax', 'grades');
+                $errors['grademax'] = get_string('incorrectminmax', 'grades');
+            }
+        }
+
+        return $errors;
+    }
+
+}
+?>
Index: grade/edit/simple_tree/category.php
===================================================================
RCS file: grade/edit/simple_tree/category.php
diff -N grade/edit/simple_tree/category.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/category.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,162 @@
+<?php  //$Id: category.php,v 1.4.2.7 2008-05-08 12:45:11 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ */
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/lib.php';
+require_once 'category_form.php';
+require_once $CFG->dirroot.'/grade/report/simple_grader/lib/simple_grade_hook.php';
+
+$courseid = required_param('courseid', PARAM_INT);
+$id       = optional_param('id', 0, PARAM_INT);
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+require_capability('moodle/grade:manage', $context);
+
+// default return url
+$gpr = new grade_plugin_return();
+$returnurl = $gpr->get_return_url('index.php?id='.$course->id);
+
+
+$mform = new edit_category_form(null, array('gpr'=>$gpr));
+
+if ($id) {
+    if (!$grade_category = grade_category::fetch(array('id'=>$id, 'courseid'=>$course->id))) {
+        error('Incorrect category id!');
+    }
+    $grade_category->apply_forced_settings();
+    $category = $grade_category->get_record_data();
+    // Get Category preferences
+    $category->pref_aggregationview = grade_report::get_pref('aggregationview', $id);
+    // Load agg coef
+    $grade_item = $grade_category->load_grade_item();
+    $category->aggregationcoef = format_float($grade_item->aggregationcoef, 4);
+    // set parent
+    $category->parentcategory = $grade_category->parent;
+
+} else {
+    $grade_category = new grade_category(array('courseid'=>$courseid), false);
+    $grade_category->apply_default_settings();
+    $grade_category->apply_forced_settings();
+
+    $category = $grade_category->get_record_data();
+    $category->aggregationcoef = format_float(1, 4);
+}
+
+$agg_only_rep = ($category->aggregateonlygraded) ? 0 : 1;
+$category->aggregateonlygraded = $agg_only_rep;
+
+$mform->set_data($category);
+
+if ($mform->is_cancelled()) {
+    redirect($returnurl);
+
+} else if ($data = $mform->get_data(false)) {
+    // If no fullname is entered for a course category, put ? in the DB
+        if (!isset($data->fullname) || $data->fullname == '') {
+            $data->fullname = '?';
+        }
+
+        if (!isset($data->aggregateonlygraded)) {
+            $data->aggregateonlygraded = 1;
+        } else {
+            $data->aggregateonlygraded = 0;
+        }
+
+        if (!isset($data->aggregateoutcomes)) {
+            $data->aggregateoutcomes = 0;
+        }
+
+        $mark_for_cleaning = false;
+        if ($data->aggregation != $grade_category->aggregation) {
+            $mark_for_cleaning = true;
+        }
+
+        grade_category::set_properties($grade_category, $data);
+
+        if (empty($grade_category->id)) {
+            $grade_category->insert();
+
+        } else {
+            $grade_category->update();
+        }
+
+        // Handle user preferences
+        if (isset($data->pref_aggregationview)) {
+            if (!grade_report::set_pref('simple_aggregationview', $data->pref_aggregationview, $grade_category->id)) {
+                error("Could not set preference aggregationview to $value for this grade category");
+            }
+        }
+
+        // set parent if needed
+        if (isset($data->parentcategory)) {
+            $grade_category->set_parent($data->parentcategory, 'gradebook');
+        }
+
+        // update agg coef if needed
+        if (isset($data->aggregationcoef)) {
+            $data->aggregationcoef = unformat_float($data->aggregationcoef);
+            $grade_item = $grade_category->load_grade_item();
+            $grade_item->aggregationcoef = $data->aggregationcoef;
+            $grade_item->update();
+        }
+    
+        if ($mark_for_cleaning){
+            clean_aggregation_switch($grade_category);
+        }
+
+    redirect($returnurl);
+
+}
+
+
+$strgrades         = get_string('grades');
+$strgraderreport   = get_string('graderreport', 'grades');
+$strcategoriesedit = get_string('categoryedit', 'grades');
+$strcategory       = get_string('category', 'grades');
+
+$navigation = array(
+              //array('name'=> $course->shortname, 'link'=> "{$CFG->wwwroot}/course/view.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $strgrades, 'link'=>"{$CFG->wwwroot}/grade/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $strgraderreport, 'link'=>"{$CFG->wwwroot}/grade/report/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> 'EDIT', 'link'=>"{$CFG->wwwroot}/grade/edit/simple_tree/index.php?id=$course->id", 'type'=>'title'),
+              array('name'=> $strcategory, 'link' =>'', 'type'=>'title')
+            );
+
+print_header_simple($strcategory,'', build_navigation($navigation));
+
+$mform->display();
+
+print_footer($course);
+die;
Index: grade/report/simple_grader/functions.js
===================================================================
RCS file: grade/report/simple_grader/functions.js
diff -N grade/report/simple_grader/functions.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/functions.js	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,129 @@
+/** highlight/unset the row of a table **/
+function set_row(idx) {
+    var table = document.getElementById('user-grades');
+    var rowsize = table.rows[idx].cells.length;
+    for (var i = 0; i < rowsize; i++) {
+        if (table.rows[idx].cells[i]) {
+            if (table.rows[idx].cells[i].className.search(/hmarked/) != -1) {
+                table.rows[idx].cells[i].className = table.rows[idx].cells[i].className.replace(' hmarked', '');
+            } else {
+                table.rows[idx].cells[i].className += ' hmarked';
+            }
+        }
+    }
+}
+
+/** highlight/unset the column of a table **/
+function set_col(idx) {
+    var table = document.getElementById('user-grades');
+    for (var i = 1; i < table.rows.length-1; i++) {
+        if (table.rows[i].cells[idx]) {
+            if (table.rows[i].cells[idx].className.search(/vmarked/) != -1) {
+                table.rows[i].cells[idx].className = table.rows[i].cells[idx].className.replace(' vmarked', '');
+            } else {
+                table.rows[i].cells[idx].className += ' vmarked';
+            }
+        }
+    }
+}
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ * Date: 05/08/2008
+ */
+
+/** This function is used for the image zooming in the report */
+function profile_image(wwwroot, userid){
+    return '<img class="biguserpic" src="' + wwwroot + '/user/pix.php/' + userid + '/f1.jpg" alt="Student ID Photo"/>';
+}
+
+/** Simple function that enables/disables inputs for mods itemtypes */
+function toggleEdit(userid, itemid) {
+   var gradeInput = document.getElementById('grade_'+ userid + '_' + itemid);
+   var feedbackInput = document.getElementById('feedback_'+ userid + '_' + itemid);
+    
+   if (gradeInput != null && feedbackInput !=null) {
+       gradeInput.disabled = !gradeInput.disabled;
+       feedbackInput.disabled = !feedbackInput.disabled;
+   }
+}
+
+function toggleAggCoef(itemid) {
+   var itemweightInput = document.getElementById(itemid + '_item_weight');
+
+   if (itemweightInput != null && !isItemSumCat(itemid)) {
+      itemweightInput.disabled = !itemweightInput.disabled;
+   }
+}
+
+function toggleDropItemid(itemid) {
+    //extra credit box of interest
+    var xc = document.getElementById(itemid + '_extra_credit');
+
+    // Follow extra credit rules; return if applied
+    if (xc.checked) {
+        return;
+    }
+    //input of interest
+    var aggInput = document.getElementById(itemid + '_item_weight');
+
+    aggInput.disabled = isItemSumCat(itemid);
+}
+
+function isItemSumCat(itemid) {
+    // There are no sum categories, no need to process any further
+    if (sum_cats.length == 0) {
+        return false;
+    }
+
+    var selectBox = document.getElementById('menu' + itemid + '_selector');
+    var sIndex = selectBox.selectedIndex;
+
+    for (var i = 0; i < sum_cats.length; i++) {
+        // We found ourselves a match; tim eto change the element
+        if (sum_cats[i] == selectBox.options[sIndex].value) {
+            //It is a sum cat
+            return true;
+        }
+    }
+    // Didn't find it
+    return false;
+}
+
+/** Toggles checkboxes of any kinds on the page based on the search pattern */
+function toggleCheckboxes(pattern, checked) {
+    var inputElements = document.getElementsByTagName('INPUT');
+    for (var i=0 ; i< inputElements.length; i++) {
+        if (inputElements[i].name.match(pattern) && inputElements[i].type=="checkbox"
+            && !inputElements[i].disabled && inputElements[i].checked != checked) {
+
+            inputElements[i].checked = checked;
+            if (pattern == 'override'){
+                var namearr = inputElements[i].name.split('_');
+                toggleEdit(namearr[1], namearr[2]);
+            }
+        }
+    }
+}
+
+function submitWarning(link) {
+    var found = false;
+    var inputElements = document.getElementsByTagName('INPUT');
+    for(var i=0; i < inputElements.length; i++) {
+        var curInput = inputElements[i];
+        if (curInput.type != 'text') {
+            continue;
+        }
+        var oldval = document.getElementById('old' + curInput.id);
+        if (oldval.value != curInput.value) {
+            found = true;
+            break;
+        } 
+    }
+    
+    if (found) {
+        alert("WARNING: There are some unsaved changes to the gradebook.\n Save the changes with the 'Update' button at\n the bottom of the page.");
+    } else {
+        window.location = link;
+    }
+}
Index: grade/edit/simple_tree/index.php
===================================================================
RCS file: grade/edit/simple_tree/index.php
diff -N grade/edit/simple_tree/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,294 @@
+<?php  // $Id: index.php,v 1.12.2.6 2008-05-08 19:11:29 pcali1  Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ * Date: 05/08/2008
+ */
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences
+require_once $CFG->dirroot.'/grade/report/simple_grader/lib/simple_grade_hook.php';
+
+$courseid = required_param('id', PARAM_INT);
+$action   = optional_param('action', 0, PARAM_ALPHA);
+$eid      = optional_param('eid', 0, PARAM_ALPHANUM);
+
+
+/// Make sure they can even access this course
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+require_capability('moodle/grade:manage', $context);
+
+/// return tracking object
+$gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'simple_tree', 'courseid'=>$courseid));
+$returnurl = $gpr->get_return_url(null);
+
+//first make sure we have proper final grades - we need it for locking changes
+simple_grade_regrade_final_grades($courseid);
+
+// get the grading tree object
+// note: total must be first for moving to work correctly, if you want it last moving code must be rewritten!
+$gtree = new grade_tree($courseid, false, false);
+
+if (empty($eid)) {
+    $element = null;
+    $object  = null;
+
+} else {
+    if (!$element = $gtree->locate_element($eid)) {
+        error('Incorrect element id!', $returnurl);
+    }
+    $object = $element['object'];
+}
+
+$switch = grade_get_setting($course->id, 'aggregationposition', $CFG->grade_aggregationposition);
+
+$strgrades             = get_string('grades');
+$strgraderreport       = get_string('graderreport', 'grades');
+$strcategoriesedit     = get_string('categoriesedit', 'grades');
+$strcategoriesanditems = get_string('categoriesanditems', 'grades');
+
+$navigation = grade_build_nav(__FILE__, $strcategoriesanditems, array('courseid' => $courseid));
+
+$moving = false;
+
+switch ($action) {
+    case 'delete':
+        if ($eid) {
+            if (!element_deletable($element)) {
+                // no deleting of external activities - they would be recreated anyway!
+                // exception is activity without grading or misconfigured activities
+                break;
+            }
+            $confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+            if ($confirm and confirm_sesskey()) {
+                if (get_class($object) == 'grade_item') {
+                    $parent_category = $object->get_parent_category();
+                    $object->delete('grade/report/grader/category');
+                    derive_sum_max($parent_category);
+                } else {
+                    $object->delete('grade/report/grader/category'); 
+                }
+                redirect($returnurl);
+
+            } else {
+                print_header_simple('', '', build_navigation($navigation));
+                $strdeletecheckfull = get_string('deletecheck', '', $object->get_name());
+                $optionsyes = array('eid'=>$eid, 'confirm'=>1, 'sesskey'=>sesskey(), 'id'=>$course->id, 'action'=>'delete');
+                $optionsno  = array('id'=>$course->id);
+                notice_yesno($strdeletecheckfull, 'index.php', 'index.php', $optionsyes, $optionsno, 'post', 'get');
+                print_footer($course);
+                die;
+            }
+        }
+        break;
+
+    case 'autosort':
+        //TODO: implement autosorting based on order of mods on course page, categories first, manual items last
+        break;
+
+    case 'synclegacy':
+        grade_grab_legacy_grades($course->id);
+        redirect($returnurl);
+
+    case 'move':
+        if ($eid and confirm_sesskey()) {
+            $moveafter = required_param('moveafter', PARAM_ALPHANUM);
+            if(!$after_el = $gtree->locate_element($moveafter)) {
+                error('Incorect element id in moveafter', $returnurl);
+            }
+            $after = $after_el['object'];
+            $parent = $after->get_parent_category();
+            $sortorder = $after->get_sortorder();
+
+            $object->set_parent($parent->id);
+            $object->move_after_sortorder($sortorder);
+
+            redirect($returnurl);
+        }
+        break;
+
+    case 'moveselect':
+        if ($eid and confirm_sesskey()) {
+            $moving = $eid;
+        }
+        break;
+
+    default:
+        break;
+}
+
+//print_header_simple('', '', build_navigation($navigation));
+print_header_simple($strgrades . ': ' . $strgraderreport, ': ' . $strcategoriesedit, $navigation, '', '', true, '', navmenu($course));
+
+/// Print the plugin selector at the top
+print_grade_plugin_selector($courseid, 'edit', 'simple_tree');
+
+//Add the QE link in the header
+print_heading(get_string('categoriesedit', 'grades') . ' <a href="'.
+        $CFG->wwwroot.'/grade/report/simple_grader/quick_edit.php?id='.$courseid.'">QE</a>');
+
+
+print_box_start('gradetreebox generalbox');
+echo '<ul id="grade_tree">';
+print_grade_tree($gtree, $gtree->top_element, $moving, $gpr, $switch);
+echo '</ul>';
+print_box_end();
+
+echo '<div class="buttons">';
+if ($moving) {
+    print_single_button('index.php', array('id'=>$course->id), get_string('cancel'), 'get');
+} else {
+    print_single_button('category.php', array('courseid'=>$course->id), get_string('addcategory', 'grades'), 'get');
+    print_single_button('item.php', array('courseid'=>$course->id), get_string('additem', 'grades'), 'get');
+    if (!empty($CFG->enableoutcomes)) {
+        print_single_button('outcomeitem.php', array('courseid'=>$course->id), get_string('addoutcomeitem', 'grades'), 'get');
+    }
+    //print_single_button('index.php', array('id'=>$course->id, 'action'=>'autosort'), get_string('autosort', 'grades'), 'get');
+    print_single_button('index.php', array('id'=>$course->id, 'action'=>'synclegacy'), get_string('synclegacygrades', 'grades'), 'get');
+}
+echo '</div>';
+print_footer($course);
+die;
+
+/**
+ * TODO document
+ */
+function print_grade_tree(&$gtree, $element, $moving, &$gpr, $switch, $switchedlast=false) {
+    global $CFG, $COURSE;
+
+/// fetch needed strings
+    $strmove     = get_string('move');
+    $strmovehere = get_string('movehere');
+    $strdelete   = get_string('delete');
+
+    $object = $element['object'];
+    $eid    = $element['eid'];
+
+    $header = $gtree->get_element_header($element, true, true, true);
+
+    if ($object->is_hidden()) {
+        $header = '<span class="dimmed_text">'.$header.'</span>';
+    }
+
+/// prepare actions
+    //the get_edit_icon method routes to the wrong plugin
+    $actions = $gtree->get_edit_icon($element, $gpr);
+    $actions = str_replace('edit/tree/', 'edit/simple_tree/', $actions);
+    //no calculations
+    //$actions .= $gtree->get_calculation_icon($element, $gpr);
+
+    if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) {
+        if (element_deletable($element)) {
+            $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=delete&amp;eid='
+                     . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'
+                     . $strdelete.'" title="'.$strdelete.'"/></a>';
+        }
+        $actions .= '<a href="index.php?id='.$COURSE->id.'&amp;action=moveselect&amp;eid='
+                 . $eid.'&amp;sesskey='.sesskey().'"><img src="'.$CFG->pixpath.'/t/move.gif" class="iconsmall" alt="'
+                 . $strmove.'" title="'.$strmove.'"/></a>';
+    }
+
+    $actions .= $gtree->get_hiding_icon($element, $gpr);
+    $actions .= $gtree->get_locking_icon($element, $gpr);
+
+/// prepare move target if needed
+    $last = '';
+    $catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem');
+    $moveto = '';
+    if ($moving) {
+        $actions = ''; // no action icons when moving
+        $moveto = '<li><a href="index.php?id='.$COURSE->id.'&amp;action=move&amp;eid='.$moving.'&amp;moveafter='
+                . $eid.'&amp;sesskey='.sesskey().'"><img class="movetarget" src="'.$CFG->wwwroot.'/pix/movehere.gif" alt="'
+                . $strmovehere.'" title="'.$strmovehere.'" /></a></li>';
+    }
+
+/// print the list items now
+    if ($moving == $eid) {
+        // do not diplay children
+        echo '<li class="'.$element['type'].' moving">'.$header.'('.get_string('move').')</li>';
+
+    } else if ($element['type'] != 'category') {
+        if ($catcourseitem and $switch) {
+            if ($switchedlast) {
+                echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>';
+            } else {
+                echo $moveto;
+            }
+        } else {
+            echo '<li class="'.$element['type'].'">'.$header.$actions.'</li>'.$moveto;
+        }
+
+    } else {
+        echo '<li class="'.$element['type'].'">'.$header.$actions;
+        echo '<ul class="catlevel'.$element['depth'].'">';
+        $last = null;
+        foreach($element['children'] as $child_el) {
+            if ($switch and empty($last)) {
+                $last = $child_el;
+            }
+            print_grade_tree($gtree, $child_el, $moving, $gpr, $switch);
+        }
+        if ($last) {
+            print_grade_tree($gtree, $last, $moving, $gpr, $switch, true);
+        }
+        echo '</ul></li>';
+        if ($element['depth'] > 1) {
+            echo $moveto; // can not move after the top category
+        }
+    }
+}
+
+function element_deletable($element) {
+    global $COURSE;
+
+    if ($element['type'] != 'item') {
+        return true;
+    }
+
+    $grade_item = $element['object'];
+    
+    if ($grade_item->itemtype != 'mod' or $grade_item->is_outcome_item() or $grade_item->gradetype == GRADE_TYPE_NONE) {
+        return true;
+    }
+
+    $modinfo = get_fast_modinfo($COURSE);
+    if (!isset($modinfo->instances[$grade_item->itemmodule][$grade_item->iteminstance])) {
+        // module does not exist
+        return true;
+    }
+
+    return false;
+}
+
+?>
Index: grade/import/mymathlab/import.php
===================================================================
RCS file: grade/import/mymathlab/import.php
diff -N grade/import/mymathlab/import.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/import.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,131 @@
+<?php
+
+/**
+ * @author Adam Zapletal
+ * Louisiana State University
+ */
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/import/lib.php';
+
+///////////////////////////////////////////////////////////////////////////////
+
+$id = required_param('id', PARAM_INT); // course id
+
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+
+echo require_js(array('yui_yahoo', 'yui_dom-event', 'yui_animation', 'yui_event', 
+                      'yui_connection', 'functions.js'));
+
+$context = get_context_instance(CONTEXT_COURSE, $id);
+
+require_capability('moodle/grade:import', $context);
+require_capability('gradeimport/mymathlab:view', $context);
+
+$CFG->stylesheets[] = $CFG->wwwroot . '/grade/import/mymathlab/style.css';
+
+$actionstr = get_string('modulename', 'gradeimport_mymathlab');
+$navigation = grade_build_nav(__FILE__, $actionstr, array('courseid' => $course->id));
+
+print_header($course->shortname.': '.get_string('grades'), $course->fullname, $navigation);
+print_grade_plugin_selector($id, 'import', 'mymathlab');
+
+///////////////////////////////////////////////////////////////////////////////
+
+$clean_data = array();
+
+if ($raw_data = data_submitted()) {
+    foreach ($raw_data as $key => $value) {
+        $clean_data[$key] = clean_param($value, PARAM_CLEAN);
+    }
+}
+
+$math_ids_to_grades = $SESSION->mymathlab_grades;
+$moodle_ids_to_grades = array();
+
+// Map moodle grade item ids to math grades
+foreach ($clean_data as $k => $v) {
+    if (strstr($k, 'grade_mapping_') == $k) {
+        $moodle_ids_to_grades[$v] = $math_ids_to_grades[end(explode('_', $k))];
+    }
+}
+
+// Insert grades
+// Much of this code is taken from insert_grades in smart importer's classes.php
+
+$successes = 0;
+
+foreach ($moodle_ids_to_grades as $gi_id => $grades) {
+    $importcode = get_new_importcode();
+
+    $gi_params = array('id' => $gi_id, 'courseid' => $id);
+
+    if (!$grade_items = grade_item::fetch_all($gi_params)) {
+        // I provide the grade item selection, so this should never happen
+        echo get_string('bad_grade_item_id', 'gradeimport_smart');
+    
+        continue;
+    } else if (count($grade_items) != 1) {
+        // Again, this should never happen
+        echo get_string('duped_grade_item_id', 'gradeimport_smart');
+    
+        continue;
+    } else {
+        $grade_item = reset($grade_items);
+    }
+
+    // Can't insert grades if the item is locked
+    if ($grade_item->is_locked()) {
+        echo get_string('gradeitemlocked', 'grades');
+
+        continue;
+    }
+
+    foreach ($grades as $userid => $grade) {
+        // Make sure grade_grade isn't locked
+        if ($grade_grade = new grade_grade(array('itemid'=>$gi_id, 'userid'=>$userid))) {
+            $grade_grade->grade_item =& $grade_item;
+
+            if ($grade_grade->is_locked()) {
+                // individual grade locked, abort
+                echo get_string('gradelocked', 'grades');
+
+                continue;
+            }
+        }
+
+        $newgrade = new object();
+        $newgrade->itemid     = $grade_item->id;
+        $newgrade->userid     = $userid;
+        $newgrade->importcode = $importcode;
+        $newgrade->importer   = $USER->id;
+        $newgrade->finalgrade = $grade;
+
+        // Try to insert newgrade into temp table
+        if (!insert_record('grade_import_values', addslashes_recursive($newgrade))) {
+            echo get_string('importfailed', 'grades');
+        }
+    }
+
+    grade_import_commit($id, $importcode, false, false);
+
+    $successes++;
+}
+
+$success_text = get_string('success', 'gradeimport_mymathlab');
+echo '<div class = "success">' . $successes . ' ' . $success_text . '</div>';
+echo '<br />';
+echo '<div class = "continue">';
+print_continue($CFG->wwwroot . '/grade/report/index.php?id=' . $id);
+echo '</div>';
+
+///////////////////////////////////////////////////////////////////////////////
+
+print_footer();
+
+?>
Index: grade/edit/custom_letter/tabs.php
===================================================================
RCS file: grade/edit/custom_letter/tabs.php
diff -N grade/edit/custom_letter/tabs.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/tabs.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,43 @@
+<?php  // $Id: tabs.php,v 1.3 2008-05-09 07:42:31 rrusso Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+    $row = $tabs = array();
+
+    $row[] = new tabobject('lettersview',
+                           $CFG->wwwroot.'/grade/edit/custom_letter/index.php?id='.$COURSE->id,
+                           get_string('letters', 'grades'));
+
+    if (has_capability('moodle/grade:manageletters', $context)) {
+        $row[] = new tabobject('lettersedit',
+                               $CFG->wwwroot.'/grade/edit/custom_letter/edit.php?id='.$context->id,
+                               get_string('edit'));
+    }
+
+    $tabs[] = $row;
+
+    echo '<div class="letterdisplay">';
+    print_tabs($tabs, $currenttab);
+    echo '</div>';
+
+?>
Index: grade/edit/simple_tree/grade.php
===================================================================
RCS file: grade/edit/simple_tree/grade.php
diff -N grade/edit/simple_tree/grade.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/grade.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,276 @@
+<?php  //$Id: grade.php,v 1.18.2.3 2008-03-15 14:54:07 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/lib.php';
+require_once 'grade_form.php';
+
+$courseid = required_param('courseid', PARAM_INT);
+$id       = optional_param('id', 0, PARAM_INT);
+$itemid   = optional_param('itemid', 0, PARAM_INT);
+$userid   = optional_param('userid', 0, PARAM_INT);
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+if (!has_capability('moodle/grade:manage', $context)) {
+    require_capability('moodle/grade:edit', $context);
+}
+
+// default return url
+$gpr = new grade_plugin_return();
+$returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/report.php?id='.$course->id);
+
+// security checks!
+if (!empty($id)) {
+    if (!$grade = get_record('grade_grades', 'id', $id)) {
+        error('Incorrect grade id');
+    }
+
+    if (!empty($itemid) and $itemid != $grade->itemid) {
+        error('Incorrect itemid');
+    }
+    $itemid = $grade->itemid;
+
+    if (!empty($userid) and $userid != $grade->userid) {
+        error('Incorrect userid');
+    }
+    $userid = $grade->userid;
+
+    unset($grade);
+
+} else if (empty($userid) or empty($itemid)) {
+    error('Missing userid and itemid');
+}
+
+if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) {
+    error('Can not find grade_item');
+}
+
+// now verify grading user has access to all groups or is member of the same group when separate groups used in course
+if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
+    if ($groups = groups_get_all_groups($COURSE->id, $userid)) {
+        $ok = false;
+        foreach ($groups as $group) {
+            if (groups_is_member($group->id, $USER->id)) {
+                $ok = true;
+            }
+        }
+        if (!$ok) {
+            error('Can not grade this user');
+        }
+    } else {
+        error('Can not grade this user');
+    }
+}
+
+$mform = new edit_grade_form(null, array('grade_item'=>$grade_item, 'gpr'=>$gpr));
+
+if ($grade = get_record('grade_grades', 'itemid', $grade_item->id, 'userid', $userid)) {
+
+    // always clean existing feedback - grading should not have XSS risk
+    if (can_use_html_editor()) {
+        if (empty($grade->feedback)) {
+            $grade->feedback  = '';
+        } else {
+            $options = new object();
+            $options->smiley  = false;
+            $options->filter  = false;
+            $options->noclean = false;
+            $grade->feedback  = format_text($grade->feedback, $grade->feedbackformat, $options);
+        }
+        $grade->feedbackformat = FORMAT_HTML;
+    } else {
+        $grade->feedback       = clean_text($grade->feedback, $grade->feedbackformat);
+    }
+
+    $grade->locked      = $grade->locked     > 0 ? 1:0;
+    $grade->overridden  = $grade->overridden > 0 ? 1:0;
+    $grade->excluded    = $grade->excluded   > 0 ? 1:0;
+
+    if ($grade->hidden > 1) {
+        $grade->hiddenuntil = $grade->hidden;
+        $grade->hidden = 1;
+    } else {
+        $grade->hiddenuntil = 0;
+    }
+
+    if ($grade_item->is_hidden()) {
+        $grade->hidden = 1;
+    }
+
+    if ($grade_item->is_locked()) {
+        $grade->locked = 1;
+    }
+
+    // normalize the final grade value
+    if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+        if (empty($grade->finalgrade)) {
+            $grade->finalgrade = -1;
+        } else {
+            $grade->finalgrade = (int)$grade->finalgrade;
+        }
+    } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
+        $grade->finalgrade = format_float($grade->finalgrade, $grade_item->get_decimals());
+    }
+
+    $grade->oldgrade    = $grade->finalgrade;
+    $grade->oldfeedback = $grade->feedback;
+
+    $mform->set_data($grade);
+
+} else {
+    $mform->set_data(array('itemid'=>$itemid, 'userid'=>$userid, 'locked'=>$grade_item->locked, 'locktime'=>$grade_item->locktime));
+}
+
+if ($mform->is_cancelled()) {
+    redirect($returnurl);
+
+// form processing
+} else if ($data = $mform->get_data(false)) {
+    $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet
+
+    // fix no grade for scales
+    if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) {
+        $data->finalgrade = $old_grade_grade->finalgrade;
+
+    } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+        if ($data->finalgrade < 1) {
+            $data->finalgrade = NULL;
+        }
+
+    } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
+        $data->finalgrade = unformat_float($data->finalgrade);
+
+    } else {
+        //this shoul not happen
+        $data->finalgrade = $old_grade_grade->finalgrade;
+    }
+
+    // the overriding of feedback is tricky - we have to care about external items only
+    if (!array_key_exists('feedback', $data) or $data->feedback == $data->oldfeedback) {
+        $data->feedback       = $old_grade_grade->feedback;
+        $data->feedbackformat = $old_grade_grade->feedbackformat;
+    }
+    // update final grade or feedback
+    $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat);
+
+    $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
+    $grade_grade->grade_item =& $grade_item; // no db fetching
+
+    if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) {
+        if (!grade_floats_different($data->finalgrade, $old_grade_grade->finalgrade)
+          and $data->feedback === $old_grade_grade->feedback) {
+            // change overridden flag only if grade or feedback not changed
+            if (!isset($data->overridden)) {
+                $data->overridden = 0; // checkbox
+            }
+            $grade_grade->set_overridden($data->overridden);
+        }
+    }
+
+    if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) {
+        $hidden      = empty($data->hidden) ? 0: $data->hidden;
+        $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
+
+        if ($grade_item->is_hidden()) {
+            if ($old_grade_grade->hidden == 1 and $hiddenuntil == 0) {
+                //nothing to do - grade was originally hidden, we want to keep it that way
+            } else {
+                $grade_grade->set_hidden($hiddenuntil);
+            }
+        } else {
+            if ($hiddenuntil) {
+                $grade_grade->set_hidden($hiddenuntil);
+            } else {
+                $grade_grade->set_hidden($hidden); // checkbox data might be undefined
+            }
+        }
+    }
+
+    if (isset($data->locked) and !$grade_item->is_locked()) {
+        if (($old_grade_grade->locked or $old_grade_grade->locktime)
+          and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) {
+            //ignore data
+
+        } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime)
+          and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) {
+            //ignore data
+
+        } else {
+            $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime
+            $grade_grade->set_locked($data->locked, false, true);
+            // reload grade in case it was regraded from activity
+            $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
+            $grade_grade->grade_item =& $grade_item; // no db fetching
+        }
+    }
+
+    if (isset($data->excluded) and has_capability('moodle/grade:manage', $context)) {
+        $grade_grade->set_excluded($data->excluded);
+    }
+
+    // detect cases when we need to do full regrading
+    if ($old_grade_grade->excluded != $grade_grade->excluded) {
+        $parent = $grade_item->get_parent_category();
+        $parent->force_regrading();
+
+    } else if ($old_grade_grade->overridden != $grade_grade->overridden and empty($grade_grade->overridden)) { // only when unoverriding
+        $grade_item->force_regrading();
+
+    } else if ($old_grade_grade->locktime != $grade_grade->locktime) {
+        $grade_item->force_regrading();
+    }
+
+    redirect($returnurl);
+}
+
+$strgrades       = get_string('grades');
+$strgraderreport = get_string('graderreport', 'grades');
+$strgradeedit    = get_string('editgrade', 'grades');
+$struser         = get_string('user');
+
+$navigation = grade_build_nav(__FILE__, $strgradeedit, array('courseid' => $courseid));
+
+/*********** BEGIN OUTPUT *************/
+
+print_header_simple($strgrades . ': ' . $strgraderreport . ': ' . $strgradeedit,
+    ': ' . $strgradeedit , $navigation, '', '', true, '', navmenu($course));
+
+print_heading($strgradeedit);
+
+print_simple_box_start("center");
+
+// Form if in edit or add modes
+$mform->display();
+
+print_simple_box_end();
+
+print_footer($course);
+die;
Index: blocks/anonymous_grade/db/install.xml
===================================================================
RCS file: blocks/anonymous_grade/db/install.xml
diff -N blocks/anonymous_grade/db/install.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/db/install.xml	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="blocks/anonymous_grade/db" VERSION="20080507" COMMENT="XMLDB file for block blocks/anonymous_grade"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+  <TABLES>
+    <TABLE NAME="block_anonymous_grade_config" COMMENT="Stores the config for anonymous" NEXT="block_anon_grade_items">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="name"/>
+        <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="value"/>
+        <FIELD NAME="value" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="name"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+    </TABLE>
+    <TABLE NAME="block_anon_grade_items" COMMENT="Default comment for the table, please edit me" PREVIOUS="block_anonymous_grade_config" NEXT="block_anon_grade_grades">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="itemid"/>
+        <FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="completed"/>
+        <FIELD NAME="completed" TYPE="int" LENGTH="1" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="itemid"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+    </TABLE>
+    <TABLE NAME="block_anon_grade_grades" COMMENT="Default comment for the table, please edit me" PREVIOUS="block_anon_grade_items" NEXT="block_anon_grade_adjustments">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="itemid"/>
+        <FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="userid"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="itemid" NEXT="rawgrade"/>
+        <FIELD NAME="rawgrade" TYPE="number" LENGTH="10" NOTNULL="false" UNSIGNED="false" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="userid" NEXT="rawgrademax"/>
+        <FIELD NAME="rawgrademax" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="100.00000" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="rawgrade" NEXT="rawgrademin"/>
+        <FIELD NAME="rawgrademin" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0.00000" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="rawgrademax" NEXT="rawscaleid"/>
+        <FIELD NAME="rawscaleid" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="rawgrademin" NEXT="usermodified"/>
+        <FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="rawscaleid" NEXT="finalgrade"/>
+        <FIELD NAME="finalgrade" TYPE="number" LENGTH="10" NOTNULL="false" UNSIGNED="false" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="usermodified" NEXT="hidden"/>
+        <FIELD NAME="hidden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="finalgrade" NEXT="locked"/>
+        <FIELD NAME="locked" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="hidden" NEXT="locktime"/>
+        <FIELD NAME="locktime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="locked" NEXT="exported"/>
+        <FIELD NAME="exported" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="locktime" NEXT="overridden"/>
+        <FIELD NAME="overridden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="exported" NEXT="excluded"/>
+        <FIELD NAME="excluded" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="overridden" NEXT="feedback"/>
+        <FIELD NAME="feedback" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" ENUM="false" PREVIOUS="excluded" NEXT="feedbackformat"/>
+        <FIELD NAME="feedbackformat" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="feedback" NEXT="information"/>
+        <FIELD NAME="information" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" ENUM="false" PREVIOUS="feedbackformat" NEXT="informationformat"/>
+        <FIELD NAME="informationformat" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="information" NEXT="timecreated"/>
+        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="informationformat" NEXT="timemodified"/>
+        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="timecreated"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+      </KEYS>
+    </TABLE>
+    <TABLE NAME="block_anon_grade_adjustments" COMMENT="Default comment for the table, please edit me" PREVIOUS="block_anon_grade_grades">
+      <FIELDS>
+        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="userid"/>
+        <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="itemid"/>
+        <FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" PREVIOUS="userid" NEXT="adjust_value"/>
+        <FIELD NAME="adjust_value" TYPE="number" LENGTH="6" NOTNULL="true" UNSIGNED="false" DEFAULT="0.00000" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="itemid" NEXT="grade_before"/>
+        <FIELD NAME="grade_before" TYPE="number" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" DECIMALS="5" PREVIOUS="adjust_value"/>
+      </FIELDS>
+      <KEYS>
+        <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="user"/>
+        <KEY NAME="user" TYPE="foreign" FIELDS="userid" REFTABLE="mdl_user" REFFIELDS="id" PREVIOUS="primary" NEXT="item"/>
+        <KEY NAME="item" TYPE="foreign" FIELDS="itemid" REFTABLE="mdl_grade_items" REFFIELDS="id" PREVIOUS="user"/>
+      </KEYS>
+    </TABLE>
+  </TABLES>
+</XMLDB>
Index: grade/report/projected/lib.php
===================================================================
RCS file: grade/report/projected/lib.php
diff -N grade/report/projected/lib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/lib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,484 @@
+<?php // $Id: lib.php,v 1.18.2.12 2007-11-01 11:45:04 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+// Projected Grade Report
+// Adapted from User Report
+// Edited by Adam Zapletal
+// February 27, 2008
+
+/**
+ * File in which the user_report class is defined.
+ * @package gradebook
+ */
+
+require_once($CFG->dirroot . '/grade/report/lib.php');
+require_once($CFG->libdir.'/tablelib.php');
+
+/**
+ * Class providing an API for the user report building and displaying.
+ * @uses grade_report
+ * @package gradebook
+ */
+class grade_report_projected extends grade_report {
+
+    /**
+     * The user.
+     * @var object $user
+     */
+    var $user;
+
+    /**
+     * A flexitable to hold the data.
+     * @var object $table
+     */
+    var $table;
+
+    /**
+     * Flat structure similar to grade tree
+     */
+    var $gseq;
+
+    /**
+     * Show hidden items even when user does not have required cap
+     */
+    var $showhiddenitems;
+
+    // adamzap
+    // init ajax_data
+    private $ajax_data = array('items' => array(), 'categories' => array());
+
+    /**
+     * Constructor. Sets local copies of user preferences and initialises grade_tree.
+     * @param int $courseid
+     * @param object $gpr grade plugin return tracking object
+     * @param string $context
+     * @param int $userid The id of the user
+     */
+    function grade_report_projected($courseid, $gpr, $context, $userid) {
+        global $CFG;
+        parent::grade_report($courseid, $gpr, $context);
+
+        $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_projected_showhiddenitems);
+
+        $switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
+
+        // Grab the grade_seq for this course
+        $this->gseq = new grade_seq($this->courseid, $switch);
+
+        // get the user (for full name)
+        $this->user = get_record('user', 'id', $userid);
+
+        // base url for sorting by first/last name
+        $this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&amp;userid='.$userid;
+        $this->pbarurl = $this->baseurl;
+
+        // no groups on this report - rank is from all course users
+        $this->setup_table();
+    }
+
+    /**
+     * Prepares the headers and attributes of the flexitable.
+     */
+    function setup_table() {
+        global $CFG;
+        /*
+         * Table has 5-6 columns
+         *| itemname | category | final grade |
+         */
+         
+        // adamzap
+        // Edited table headers
+
+        // setting up table headers
+        $tablecolumns = array('itemname', 'category', 'grade');
+        $tableheaders = array($this->get_lang_string('gradeitem', 'grades'), $this->get_lang_string('category'), $this->get_lang_string('grade'));
+
+        $this->table = new flexible_table('grade-report-user-'.$this->courseid);
+
+        $this->table->define_columns($tablecolumns);
+        $this->table->define_headers($tableheaders);
+        $this->table->define_baseurl($this->baseurl);
+
+        $this->table->set_attribute('cellspacing', '0');
+        $this->table->set_attribute('id', 'user-grade');
+        $this->table->set_attribute('class', 'boxaligncenter generaltable');
+
+        // not sure tables should be sortable or not, because if we allow it then sorted results distort grade category structure and sortorder
+        $this->table->set_control_variables(array(
+                TABLE_VAR_SORT    => 'ssort',
+                TABLE_VAR_HIDE    => 'shide',
+                TABLE_VAR_SHOW    => 'sshow',
+                TABLE_VAR_IFIRST  => 'sifirst',
+                TABLE_VAR_ILAST   => 'silast',
+                TABLE_VAR_PAGE    => 'spage'
+                ));
+
+        $this->table->setup();
+    }
+
+    function fill_table() {
+        global $CFG;
+
+        $numusers = $this->get_numusers(false); // total course users
+        $items =& $this->gseq->items;
+        $grades = array();
+
+        $canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->courseid));
+
+        // fetch or create all grades
+        foreach ($items as $key=>$unused) {
+            if (!$grade_grade = grade_grade::fetch(array('itemid'=>$items[$key]->id, 'userid'=>$this->user->id))) {
+                $grade_grade = new grade_grade();
+                $grade_grade->userid = $this->user->id;
+                $grade_grade->itemid = $items[$key]->id;
+            }
+            $grades[$key] = $grade_grade;
+            $grades[$key]->grade_item =& $items[$key];
+        }
+
+        if ($canviewhidden) {
+            $altered = array();
+            $unknown = array();
+        } else {
+            $hiding_affected = grade_grade::get_hiding_affected($grades, $items);
+            $altered = $hiding_affected['altered'];
+            $unknown = $hiding_affected['unknown'];
+            unset($hiding_affected);
+        }
+
+        foreach ($items as $itemid=>$unused) {
+            $grade_item  =& $items[$itemid];
+            $grade_grade =& $grades[$itemid];
+
+            // adamzap
+            // Fill course total data
+            if ($grade_item->itemtype == 'course') {
+                $ct_data = new stdClass;
+                $ct_data->calculation = $grade_item->calculation;
+                $ct_data->aggregationcoef = $grade_item->aggregationcoef;
+                $ct_data->grademin = $grade_item->grademin;
+                $ct_data->grademax = $grade_item->grademax;
+                // in case of aggregation, we'll need these values later
+                $ct_grademin = $grade_item->grademin;
+                $ct_grademax = $grade_item->grademax;
+
+                // new fields required by grade_format_gradevalue 03/11/08
+                $ct_data->gradetype = $grade_item->gradetype;
+                $ct_data->display = $grade_item->get_displaytype();
+                $ct_data->decimals = $grade_item->get_decimals();
+                $ct_data->scaleid = $grade_item->scaleid;
+                $ct_data->courseid = $grade_item->courseid;
+
+                $this->ajax_data['course_total'] = $ct_data;
+            }
+
+            // adamzap
+            // this logic was taken out because we are handling the hidden grades differently
+            // we only want to completely overlook a grade if it is not a category because
+            // category totals are needed to compute the final grade on the fly
+
+            if (!$grade_item->is_category_item()) {
+                if (!$canviewhidden and $grade_item->is_hidden()) {
+                    if ($this->showhiddenitems == 0) {
+                        // no hidden items at all
+                        continue;
+                    } else if ($this->showhiddenitems == 1 and !$grade_item->is_hiddenuntil()) {
+                        // hidden until that are still hidden are visible
+                        continue;
+                    }
+                }
+            }
+
+            $class = 'gradeitem';
+            if ($grade_item->is_course_item()) {
+                $class = 'courseitem';
+            } else if ($grade_item->is_category_item()) {
+                $class = 'categoryitem';
+               
+                // make category totals invisible to students
+                if (!$this->showhiddenitems) {
+                    if (!$canviewhidden && $grade_item->is_hidden()) {
+                        $class .= ' invisitext';
+                    }
+                } else if ($this->showhiddenitems == 1 && $grade_item->is_hiddenuntil()) {
+                    $class .= ' invisitext';
+                }
+            }
+
+            if (in_array($itemid, $unknown)) {
+                $gradeval = null;
+            } else if (array_key_exists($itemid, $altered)) {
+                $gradeval = $altered[$itemid];
+            } else {
+                $gradeval = $grade_grade->finalgrade;
+            }
+
+            $data = array();
+
+            // all users should know which items are still hidden
+            $hidden = '';
+            if ($grade_item->is_hidden()) {
+                $hidden = ' hidden ';
+            }
+
+            $element = $this->gseq->locate_element($this->gseq->get_item_eid($grade_item));
+            $header = $this->gseq->get_element_header($element, true, true, true);
+
+            /// prints grade item name
+            $data[] = '<span class="'.$hidden.$class.'">'.$header.'</span>';
+
+            /// prints category
+            $cat = $grade_item->get_parent_category();
+            $data[] = '<span class="'.$hidden.$class.'">'.$cat->get_name().'</span>';
+
+            // adamzap
+
+            // make sure that the ajax data has a key for this category
+            // also, make sure this category isn't the overall course category
+            // if not, create one and initialize arrays
+            if(!array_key_exists($cat->id, $this->ajax_data['categories']) && $cat->parent != '') {
+                $cat_data = new stdClass;
+                $cat_data->aggregation = $cat->aggregation;
+                $cat_data->aggregatesubcats = $cat->aggregatesubcats;
+                $cat_data->droplow = $cat->droplow;
+                $cat_data->keephigh = $cat->keephigh;
+                $cat_data->path = $cat->path;
+                $this->ajax_data['categories'][$cat->id] = $cat_data;
+            }
+
+            // insert grade and item data into the ajax data array
+            if ($grade_item->itemtype != 'course') {
+                $item_data = new stdClass;
+                
+                if ($grade_item->calculation) {
+                    $item_data->calculation = $grade_item->calculation;
+                    $item_data->calculated = false;
+                }
+
+                $item_data->itemtype = $grade_item->itemtype;
+                $item_data->aggregationcoef = $grade_item->aggregationcoef;
+                $item_data->grademax = $grade_item->grademax;
+                $item_data->grademin = $grade_item->grademin;
+
+                // new fields required by grade_format_gradevalue 03/11/08
+                $item_data->gradetype = $grade_item->gradetype;
+                $item_data->display = $grade_item->get_displaytype();
+                $item_data->decimals = $grade_item->get_decimals();
+                $item_data->scaleid = $grade_item->scaleid;
+                $item_data->courseid = $grade_item->courseid;
+
+                if ($grade_item->itemtype == 'category') {
+                    $item_data->categoryid = $grade_item->iteminstance; 
+                    $item_data->parent = $cat->parent;
+                    $this->ajax_data['categories'][$grade_item->iteminstance]->calculation = $grade_item->calculation;
+                } else {
+                    $item_data->categoryid = $grade_item->categoryid; 
+                }
+
+                $item_data->value = $grade_grade->finalgrade;
+
+                $this->ajax_data['items'][$grade_item->id] = $item_data;
+            }
+
+            $hidden = '';
+            if ($grade_item->is_hidden()) {
+                // can not see grades in hidden items
+                $hidden = ' hidden ';
+            } else if ($canviewhidden and $grade_grade->is_hidden()) {
+                // if user can see hidden grades, indicate which ones are hidden
+                $hidden = ' hidden ';
+            }
+
+            /// prints the grade
+            if ($grade_grade->is_excluded()) {
+                $excluded = get_string('excluded', 'grades').' ';
+            } else {
+                $excluded = '';
+            }
+
+            if ($grade_item->needsupdate) {
+                $data[] = '<span class="'.$hidden.$class.' gradingerror">'.get_string('error').'</span>';
+
+            } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$canviewhidden and $grade_grade->is_hidden()
+                   and !$grade_item->is_category_item() and !$grade_item->is_course_item()) {
+                // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
+                $data[] = '<span class="'.$hidden.$class.' datesubmitted">'.$excluded.get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort'))).'</span>';
+
+            } else {
+                if (is_null($gradeval)) {
+                // adamzap
+                // Fill course total data for aggregation
+                    if ($grade_item->itemtype == 'course') {
+                        if (!$this->ajax_data['course_total']->calculation) {
+                            $ct_cat = $grade_item->get_parent_category();
+                            $ct_data = new stdClass;
+                            $ct_data->id = $ct_cat->id;
+                            $ct_data->aggregation = $ct_cat->aggregation;
+                            $ct_data->aggregatesubcats = $ct_cat->aggregatesubcats;
+                            $ct_data->droplow = $ct_cat->droplow;
+                            $ct_data->keephigh = $ct_cat->keephigh;
+                            $ct_data->path = $ct_cat->path;
+                            $ct_data->grademin = $this->ajax_data['course_total']->grademin;
+                            $ct_data->grademax = $this->ajax_data['course_total']->grademax;
+
+                            // new fields required by grade_format_gradevalue 03/11/08
+                            $ct_data->gradetype = $this->ajax_data['course_total']->gradetype;
+                            $ct_data->display = $grade_item->get_displaytype();
+                            $ct_data->decimals = $grade_item->get_decimals();
+                            $ct_data->scaleid = $this->ajax_data['course_total']->scaleid;
+                            $ct_data->courseid = $ct_cat->courseid;
+
+                            $this->ajax_data['course_total'] = $ct_data;
+                        }
+
+                        $data[] = '<span id = "calc_total_grade" class="'.$hidden.$class.'"><b>'.$excluded. '0.00</b></span>';
+                    } else if ($grade_item->itemtype == 'category' || $grade_item->calculation) {
+                        $data[] = '<span id = "calc_item_grade_' . $itemid . '" class="'.$hidden.$class.'"><b>'.$excluded . '0.00</b></span>';
+                    } else {
+                        $data[] = '<span class="'.$hidden.$class.'"><input type = "text" size = "4" id = "calc_grade_' . $itemid . 
+                            '" /><input type = "hidden" id = "minmax_' . $itemid . '" value = "' . $grade_item->grademin . '|' . $grade_item->grademax . '"/></span>';
+                    }
+                } else {
+                    if ($grade_item->itemtype == 'course') {
+                        if (!$this->ajax_data['course_total']->calculation) {
+                            $ct_cat = $grade_item->get_parent_category();
+                            $ct_data = new stdClass;
+                            $ct_data->id = $ct_cat->id;
+                            $ct_data->aggregation = $ct_cat->aggregation;
+                            $ct_data->aggregatesubcats = $ct_cat->aggregatesubcats;
+                            $ct_data->droplow = $ct_cat->droplow;
+                            $ct_data->keephigh = $ct_cat->keephigh;
+                            $ct_data->path = $ct_cat->path;
+                            $ct_data->grademin = $this->ajax_data['course_total']->grademin;
+                            $ct_data->grademax = $this->ajax_data['course_total']->grademax;
+
+                            // new fields required by grade_format_gradevalue 03/11/08
+                            $ct_data->gradetype = $this->ajax_data['course_total']->gradetype;
+                            $ct_data->display = $grade_item->get_displaytype();
+                            $ct_data->decimals = $grade_item->get_decimals();
+                            $ct_data->scaleid = $this->ajax_data['course_total']->scaleid;
+                            $ct_data->courseid = $ct_cat->courseid;
+
+                            $this->ajax_data['course_total'] = $ct_data;
+                        }
+                        $data[] = '<span id = "calc_total_grade" class="'.$hidden.$class.'"><b>'.$excluded.grade_format_gradevalue($gradeval, $grade_item, true) . '</b></span>';
+                    } else if($grade_item->itemtype == 'category') {
+                        $data[] = '<span id = "calc_item_grade_' . $itemid . '" class="'.$hidden.$class.'"><b>'.$excluded.grade_format_gradevalue($gradeval, $grade_item, true) . '</b></span>';
+                    } else {
+                        if ($grade_item->calculation) {
+                            $data[] = '<span id = "calc_item_grade_' . $itemid . '" class="'.$hidden.$class.'"><b>'.$excluded.grade_format_gradevalue($gradeval, $grade_item, true) . '</b></span>';
+                        } else {
+                            $data[] = '<span id = "calc_item_grade_' . $itemid . '" class="'.$hidden.$class.'">'.$excluded.grade_format_gradevalue($gradeval, $grade_item, true) . '</span>';
+                        }
+                    }
+                }
+            }
+
+            // adamzap
+            // Removed percentage column
+
+            $this->table->add_data($data);
+        }
+
+        // adamzap
+        // Sort ajax_data and add it to $SESSION
+        ksort($this->ajax_data['items']);
+        ksort($this->ajax_data['categories']);
+        global $SESSION;
+        $SESSION->projected_ajax_data = $this->ajax_data;
+
+        return true;
+    }
+
+    /**
+     * Prints or returns the HTML from the flexitable.
+     * @param bool $return Whether or not to return the data instead of printing it directly.
+     * @return string
+     */
+    function print_table($return=false) {
+        ob_start();
+        $this->table->print_html();
+        $html = ob_get_clean();
+
+        if ($return) {
+            return $html;
+        } else {
+            echo $html;
+        }
+    }
+
+    /**
+     * Processes the data sent by the form (grades and feedbacks).
+     * @var array $data
+     * @return bool Success or Failure (array of errors).
+     */
+    function process_data($data) {
+    }
+}
+
+function grade_report_projected_settings_definition(&$mform) {
+    global $CFG;
+
+    $options = array(-1 => get_string('default', 'grades'),
+                      0 => get_string('hide'),
+                      1 => get_string('showhiddenuntilonly', 'grades'),
+                      2 => get_string('show'));
+
+    if (empty($CFG->grade_report_projected_showhiddenitems)) {
+        $options[-1] = get_string('defaultprev', 'grades', $options[0]);
+    } else {
+        $options[-1] = get_string('defaultprev', 'grades', $options[1]);
+    }
+
+    $mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options);
+    $mform->setHelpButton('report_user_showhiddenitems', array(false, get_string('showhiddenitems', 'grades'),
+                          false, true, false, get_string('configshowhiddenitems', 'grades')));
+}
+
+function grade_report_projected_profilereport($course, $user) {
+    if (!empty($course->showgrades)) {
+
+        $context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+        //first make sure we have proper final grades - this must be done before constructing of the grade tree
+        grade_regrade_final_grades($course->id);
+
+        /// return tracking object
+        $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
+        // Create a report instance
+        $report = new grade_report_projected($course->id, $gpr, $context, $user->id);
+
+        // print the page
+        echo '<div class="grade-report-user">'; // css fix to share styles with real report page
+        print_heading(get_string('modulename', 'gradereport_user'). ' - '.fullname($report->user));
+
+        if ($report->fill_table()) {
+            echo $report->print_table(true);
+        }
+        echo '</div>';
+    }
+}
+
+?>
Index: grade/edit/custom_letter/index.php
===================================================================
RCS file: grade/edit/custom_letter/index.php
diff -N grade/edit/custom_letter/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,84 @@
+<?php // $Id: index.php,v 1.5 2008-05-09 07:41:22 rrusso Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->libdir.'/gradelib.php';
+
+$courseid  = optional_param('id', SITEID, PARAM_INT);
+$action   = optional_param('action', '', PARAM_ALPHA);
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:manageletters', $context)) {
+    error('Missing permission to view letter grades');
+}
+
+$gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'letter', 'courseid'=>$courseid));
+
+$strgrades = get_string('grades');
+$pagename  = get_string('letters', 'grades');
+
+$navigation = grade_build_nav(__FILE__, $pagename, $courseid);
+
+/// Print header
+print_header_simple($strgrades.': '.$pagename, ': '.$strgrades, $navigation, '', '', true, '', navmenu($course));
+/// Print the plugin selector at the top
+print_grade_plugin_selector($courseid, 'edit', 'letter');
+
+print_grade_plugin_selector($courseid, 'edit', 'tree', true);
+
+$currenttab = 'lettersview';
+require('tabs.php');
+
+$letters = grade_get_letters($context);
+
+$data = array();
+
+$max = 100;
+foreach($letters as $boundary=>$letter) {
+    $line = array();
+    $line[] = format_float($max,2).' %';
+    $line[] = format_float($boundary,2).' %';
+    $line[] = format_string($letter);
+    $data[] = $line;
+    $max = $boundary - 0.01;
+}
+
+$table = new object();
+$table->head  = array(get_string('max', 'grades'), get_string('min', 'grades'), get_string('letter', 'grades'));
+$table->size  = array('30%', '30%', '40%');
+$table->align = array('left', 'left', 'left');
+$table->width = '30%';
+$table->data  = $data;
+print_table($table);
+
+print_footer($course);
+
+?>
Index: grade/import/mymathlab/functions.js
===================================================================
RCS file: grade/import/mymathlab/functions.js
diff -N grade/import/mymathlab/functions.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/functions.js	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,56 @@
+// Add in_array to array objects
+Array.prototype.in_array = function(value) {
+    if (null == value) {
+        return false;
+    }
+
+    for(var i = 0; i < this.length; i++) {
+        if(this[i] == value) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+// Ensures that the user has chosen a file to upload
+function validate_index() {
+    if (!document.getElementsByName('mymathlab_file')[0].value) {
+        document.getElementById('error').innerHTML = 'Please choose a file to upload';
+        return false;
+    }
+
+    return true;
+}
+
+// Ensures that the user has chosen a grade item for all mappings
+function validate_mapping() {
+    var inputs = document.getElementsByTagName('select');
+    var selected = Array();
+
+    for(var i = 0; i < inputs.length; i++) {
+        if(inputs[i].name.search('grade_mapping_') > -1) {
+            var si = inputs[i].selectedIndex;
+
+            if (si == 0) {
+                var s = 'Please select a grade item for each mapping';
+                document.getElementById('error').innerHTML = s;
+
+                return false;
+            } else {
+                if (!selected.in_array(si)) {
+                    selected.push(si);
+                } else {
+                    var s = 'Please select a unique grade item for each mapping';
+                    document.getElementById('error').innerHTML = s;
+
+                    return false;
+                }
+            }
+        }
+    }
+
+    document.getElementById('error').innerHTML = '&nbsp;';
+
+    return true;
+}
Index: grade/report/projected/index.php
===================================================================
RCS file: grade/report/projected/index.php
diff -N grade/report/projected/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,120 @@
+<?php // $Id: index.php,v 1.26.2.1 2007-10-27 20:36:34 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+// Projected Grade Report
+// Adapted from User Report
+// Edited by Adam Zapletal
+// February 27, 2008
+
+require_once '../../../config.php';
+require_once $CFG->libdir.'/gradelib.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/projected/lib.php';
+
+echo require_js(array('yui_yahoo', 'yui_event', 'yui_connection', 
+    $CFG->wwwroot . '/grade/report/projected/projected-min.js'));
+
+$courseid = required_param('id');
+$userid   = optional_param('userid', $USER->id, PARAM_INT);
+
+/// basic access checks
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+require_login($course);
+
+if (!$user = get_complete_user_data('id', $userid)) {
+    error("Incorrect userid");
+}
+
+$context     = get_context_instance(CONTEXT_COURSE, $course->id);
+//$usercontext = get_context_instance(CONTEXT_PERSONAL, $user->id);
+
+require_capability('gradereport/projected:view', $context);
+
+$access = true;
+if (has_capability('moodle/grade:viewall', $context)) {
+    //ok - can view all course grades
+
+} else if ($user->id == $USER->id and has_capability('moodle/grade:view', $context) and $course->showgrades) {
+    //ok - can view own grades
+
+} else if (has_capability('moodle/grade:viewall', get_context_instance(CONTEXT_USER, $userid)) and $course->showgrades) {
+    // ok - can view grades of this user- parent most probably
+
+//} else if (has_capability('moodle/grade:view', $usercontext) and $course->showgrades) {
+    // ok - can view grades of this user- parent most probably
+
+} else {
+    $acces = false;
+}
+
+/// return tracking object
+$gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'projected', 'courseid'=>$courseid, 'userid'=>$userid));
+
+/// last selected report session tracking
+if (!isset($USER->grade_last_report)) {
+    $USER->grade_last_report = array();
+}
+$USER->grade_last_report[$course->id] = 'projected';
+
+/// Build navigation
+$strgrades  = get_string('grades');
+$reportname = get_string('modulename', 'gradereport_projected');
+
+$navigation = grade_build_nav(__FILE__, $reportname, $courseid);
+
+/// Print header
+print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation,
+                    '', '', true, '', navmenu($course));
+
+/// Print the plugin selector at the top
+print_grade_plugin_selector($courseid, 'report', 'projected');
+
+
+if ($access) {
+
+    //first make sure we have proper final grades - this must be done before constructing of the grade tree
+    grade_regrade_final_grades($courseid);
+
+    // Create a report instance
+    $report = new grade_report_projected($courseid, $gpr, $context, $userid);
+
+    // print the page
+    print_heading(get_string('modulename', 'gradereport_projected'). ' - '.fullname($report->user));
+
+    if ($report->fill_table()) {
+        echo $report->print_table(true);
+    }
+
+} else {
+    // no access to grades!
+    echo "Can not view grades."; //TODO: localize
+}
+
+echo '<br /><div id = "error"><br /></div>';
+
+print_footer($course);
+
+?>
Index: grade/import/mymathlab/style.css
===================================================================
RCS file: grade/import/mymathlab/style.css
diff -N grade/import/mymathlab/style.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/style.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,90 @@
+/* ------------------- */
+/* Style for index.php */
+/* ------------------- */
+
+/* Container for mymathlab upload form */
+#grade-import-mymathlab-index .upload_form {
+  text-align: center;
+  font-size: 10px;
+}
+
+/* --------------------- */
+/* Style for mapping.php */
+/* --------------------- */
+
+/* Container for mymathlab mapping form */
+#grade-import-mymathlab-mapping .mapping_form{
+  text-align: center;
+}
+
+/* Header row of spans */
+#grade-import-mymathlab-mapping .header_row{
+  font-weight: bold;
+}
+
+/* MyMathLab grades header span */
+#grade-import-mymathlab-mapping .math_grades_header {
+
+}
+
+/* Spacer span in header row */
+#grade-import-mymathlab-mapping .header_spacer {
+
+}
+
+/* Moodle grades header span */
+#grade-import-mymathlab-mapping .moodle_grades_header {
+
+}
+
+/* Mapping row div consisting of three spans */
+#grade-import-mymathlab-mapping .mapping_row {
+
+}
+
+/* Span containing the math grade item name */
+#grade-import-mymathlab-mapping .math_grade {
+
+}
+
+/* Span containing map to text */
+#grade-import-mymathlab-mapping .map_to {
+
+}
+
+/* Span containing the moodle grade item select */
+#grade-import-mymathlab-mapping .moodle_grade {
+
+}
+
+/* Select element that holds Moodle grades */
+#grade-import-mymathlab-mapping .mapping_select {
+
+}
+
+/* Div that notifies user that grades were converted to percents */
+#grade-import-mymathlab-mapping .converted_alert {
+  color: #008000;
+}
+
+/* Submit button for mapping form */
+#grade-import-mymathlab-mapping .mapping_submit {
+
+}
+
+/* Success messages */
+#grade-import-mymathlab-import .success {
+  color: #008000;
+  text-align: center;
+}
+
+/* Continue Link */
+#grade-import-mymathlab-import .continue {
+  text-align: center;
+}
+
+/* General style for error divs */
+.error {
+  text-align: center;
+  color: #FF0000;
+}
Index: grade/import/mymathlab/db/access.php
===================================================================
RCS file: grade/import/mymathlab/db/access.php
diff -N grade/import/mymathlab/db/access.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/db/access.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,15 @@
+<?php
+
+$gradeimport_mymathlab_capabilities = array(
+
+    'gradeimport/mymathlab:view' => array(
+        'captype' => 'write',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    )
+);
+
+?>
Index: grade/report/projected/lang/en_utf8/gradereport_projected.php
===================================================================
RCS file: grade/report/projected/lang/en_utf8/gradereport_projected.php
diff -N grade/report/projected/lang/en_utf8/gradereport_projected.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/lang/en_utf8/gradereport_projected.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,6 @@
+<?php
+
+$string['modulename'] = 'Projected Final Grade';
+$string['projected:view'] = 'Calculate your projected final grade';
+
+?>
Index: grade/edit/custom_letter/edit_form.php
===================================================================
RCS file: grade/edit/custom_letter/edit_form.php
diff -N grade/edit/custom_letter/edit_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/edit_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,102 @@
+<?php  //$Id: edit_form.php,v 1.2.2.5 2008-05-09 07:38:15 rrusso Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once $CFG->libdir.'/formslib.php';
+
+class edit_letter_form extends moodleform {
+
+    function definition() {
+        $mform =& $this->_form;
+        $num   = $this->_customdata['num'];
+        $admin = $this->_customdata['admin'];
+
+        $mform->addElement('header', 'gradeletters', get_string('gradeletters', 'grades'));
+        
+        // Only show "override site defaults" checkbox if editing the course grade letters
+        if (!$admin) {
+            $mform->addElement('checkbox', 'override', get_string('overridesitedefaultgradedisplaytype', 'grades'));
+            $mform->setHelpButton('override', array('overridesitedefaultgradedisplaytype', get_string('overridesitedefaultgradedisplaytype', 'grades'), 'grade'));
+        }
+
+        $gradeletterhelp   = get_string('configgradeletter', 'grades');
+        $gradeboundaryhelp = get_string('configgradeboundary', 'grades');
+        $gradeletter       = get_string('gradeletter', 'grades');
+        $gradeboundary     = get_string('gradeboundary', 'grades');
+
+        $letters = array();
+        $letters['A+'] = "A+";
+        $letters['A'] = "A";
+        $letters['A-'] = "A-";
+        $letters['B+'] = "B+";
+        $letters['B'] = "B";
+        $letters['B-'] = "B-";
+        $letters['C+'] = "C+";
+        $letters['C'] = "C";
+        $letters['C-'] = "C-";
+        $letters['D+'] = "D+";
+        $letters['D'] = "D";
+        $letters['D-'] = "D-";
+        $letters['P'] = "Pass";
+        $letters['F'] = "Fail";
+
+        for($i=1; $i<$num+1; $i++) {
+            $gradelettername = 'gradeletter'.$i;
+            $gradeboundaryname = 'gradeboundary'.$i;
+
+            $mform->addElement('select', $gradelettername, $gradeletter." $i", $letters);
+            if ($i == 1) {
+                $mform->setHelpButton($gradelettername, array('gradeletter', get_string('gradeletter', 'grades'), 'grade'));
+            }
+            $mform->setType($gradelettername, PARAM_TEXT);
+            
+            if (!$admin) {
+                $mform->disabledIf($gradelettername, 'override', 'notchecked');
+                $mform->disabledIf($gradelettername, $gradeboundaryname, 'eq', '');
+            }
+
+            $mform->addElement('text', $gradeboundaryname, $gradeboundary." $i");
+            if ($i == 1) {
+                $mform->setHelpButton($gradeboundaryname, array('gradeboundary', get_string('gradeboundary', 'grades'), 'grade'));
+            }
+            $mform->setDefault($gradeboundaryname, '');
+         // stop posting integers //  $mform->setType($gradeboundaryname, PARAM_INT);
+            
+            if (!$admin) {
+                $mform->disabledIf($gradeboundaryname, 'override', 'notchecked');
+            }
+        }
+
+        // hidden params
+        $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
+
+//-------------------------------------------------------------------------------
+        // buttons
+        $this->add_action_buttons(!$admin);
+    }
+
+}
+
+?>
Index: grade/report/projected/projected-min.js
===================================================================
RCS file: grade/report/projected/projected-min.js
diff -N grade/report/projected/projected-min.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/projected-min.js	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,23 @@
+
+Array.prototype.in_array=function(value){if(null==value){return false;}
+for(var i=0;i<this.length;i++){if(this[i]==value){return true;}}
+return false;}
+function addListeners(){var x=document.getElementsByTagName("input");for(var i=0;i<x.length;i++){if(x[i].type=='text'&&x[i].id.substring(5,0)=='calc_'){YAHOO.util.Event.addListener(x[i].id,"keyup",interceptKeypress,x[i]);}}}
+interval=250;lastKeypress=null;function interceptKeypress(e,elem){lastKeypress=new Date().getTime();var errorElem=document.getElementById('error');if(validInput(elem.value,e)&&checkRanges()){elem.style.backgroundColor='#FFFFFF';errorElem.innerHTML='<br />';setTimeout(function(){var currentTime=new Date().getTime();if(currentTime-lastKeypress>interval){handleEvent(e,elem);}},interval+100);}else if(e.keyCode>64&&e.keyCode<91&&!modifierDown(e)){errorElem.innerHTML='<center>Invalid Grade: '+elem.value+'</center>';elem.style.backgroundColor='#FF6666';}}
+function inRange(id){var minmax=document.getElementById('minmax_'+id).value.split('|');var value=document.getElementById('calc_grade_'+id).value;if(!(value>=parseFloat(minmax[0]))||!(value<=parseFloat(minmax[1]))){return minmax;}else{return false;}}
+function checkRanges(){var inputs=document.getElementsByTagName('input');var errorElem=document.getElementById('error');for(var i=0;i<inputs.length;i++){if(inputs[i].type=='text'){var tmp=inputs[i].id.split('_');var rangeError;if(inputs[i].value!=''){rangeError=inRange(tmp[2]);}
+if(rangeError){var s='';s='<center>Range Error: Expected '
+s+=Math.round(rangeError[0])+'-'
+s+=Math.round(rangeError[1])+'</center>';errorElem.innerHTML=s;inputs[i].style.backgroundColor='#FF6666';return false;}else{errorElem.innerHTML=s;inputs[i].style.backgroundColor='#FFFFFF';}}}
+return true;}
+function validInput(value,e){return((numberPressed(e)||e.keyCode==8||e.keyCode==46)&&!modifierDown(e))?true:false;}
+var numpadKeys=new Array(96,97,98,99,100,101,102,103,104,105);function numberPressed(e){return isFinite(parseInt(String.fromCharCode(e.keyCode)))||numpadKeys.in_array(e.keyCode);}
+function modifierDown(e){return(e.ctrlKey||e.metaKey||e.shiftKey||e.altKey);}
+function handleEvent(e,elem){var errorElem=document.getElementById('error');errorElem.innerHTML='<br />';elem.style.backgroundColor='#FFFFFF';var inputs=document.getElementsByTagName('input');var inputdata='';var fieldval;var first=true;for(var i=0;i<inputs.length;i++){if(inputs[i].type=='text'){if(!first){inputdata+='|';}
+fieldval=(inputs[i].value=='')?'switch_me':inputs[i].value;inputdata+=inputs[i].id+'='+fieldval;first=false;}}
+makeRequest(inputdata);}
+var handleSuccess=function(o){if(o.responseText!==undefined){var parts=o.responseText.split('|');for(var i=0;i<parts.length;i++){var tmp=parts[i].split('=');var elem=document.getElementById(tmp[0]);if(elem!=null){elem.innerHTML=tmp[1];}}}}
+var handleFailure=function(o){if(o.responseText!==undefined){var div=document.getElementById('error');div.innerHTML='An error has occurred';}}
+var callback={success:handleSuccess,failure:handleFailure}
+function makeRequest(inputdata){var rpcUrl='rpc.php';var postData='inputdata='+inputdata;var request=YAHOO.util.Connect.asyncRequest('POST',rpcUrl,callback,postData);}
+YAHOO.util.Event.onDOMReady(addListeners);
Index: grade/edit/simple_tree/lang/en_utf8/help/grade/extra_credit.html
===================================================================
RCS file: grade/edit/simple_tree/lang/en_utf8/help/grade/extra_credit.html
diff -N grade/edit/simple_tree/lang/en_utf8/help/grade/extra_credit.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/lang/en_utf8/help/grade/extra_credit.html	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,19 @@
+<h1>Extra Credit</h1>
+<p>By checking the extra credit box, the raw unaltered value of points awarded are added to the parent category total.</p>
+<p>You can choose to make a category extra credit by selecting the extra credit box on the category total for an entire category. this makes the value of the entire category become added to the parent category total.</p>
+
+<dl id="extra-credit-help">
+    <dt>Grades above maximum and percentages above 100</dt>
+    <dt><strong>YOU DO NOT NEED TO CHECK Extra credit TO USE THIS METHOD!</strong></dt>
+        <dd>Items can be graded up to twice their inteded score, as a result percentages and category totals can go over 100% and thei maximum as well.</dd>
+
+    <dt>Item Extra Credit</dt>
+        <dd>Each item is added to the total point value of its parent category.</dd>
+        <dd class="example">EXTRA_CREDIT 1 7/10, EXTRA CREDIT 2 2/8; parent category total 100:<br /><code>7 + 2 + 100 = 109 --> 109/100 = 109%</code></dd>
+    
+    <dt>Category Extra Credit</dt>
+        <dd>The category total is added to the total point value of its parent category. This is the most common form of extra credit.</dd>
+	<dd>Any aggregation method can be used on an extra credit category and the grades within the category behave appropriately.</dd>
+        <dd class="example">(simple weighted mean with a category point value of 10) EXTRA_CREDIT_CATEGORY grades: ex1 7/10, ex2 2/8, ex3 2/5; parent category total 100:<br /><code>((7 + 2 + 2)/23) + 100 = 104.78 --> 104.78/100 = 104.78%</code></dd>
+    
+</dl>   
Index: grade/edit/simple_tree/lang/en_utf8/help/grade/aggregationcoef.html
===================================================================
RCS file: grade/edit/simple_tree/lang/en_utf8/help/grade/aggregationcoef.html
diff -N grade/edit/simple_tree/lang/en_utf8/help/grade/aggregationcoef.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/lang/en_utf8/help/grade/aggregationcoef.html	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,2 @@
+<h1>Item weight</h1>
+<p>Weight applied to all grades in this grade item during aggregation with other grade items.</p>
Index: grade/export/csv/grade_export_csv.php
===================================================================
RCS file: grade/export/csv/grade_export_csv.php
diff -N grade/export/csv/grade_export_csv.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/grade_export_csv.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,121 @@
+<?php
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once 'csvlib.php';
+
+class grade_export_csv extends grade_export {
+
+    var $plugin = 'csv';
+
+    var $separator; // default separator
+
+    function grade_export_csv($course, $groupid=0, $itemlist='', $export_feedback=false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2, $separator='comma') {
+        $this->grade_export($course, $groupid, $itemlist, $export_feedback, $updatedgradesonly, $displaytype, $decimalpoints);
+        $this->separator = $separator;
+    }
+
+    function process_form($formdata) {
+        parent::process_form($formdata);
+        if (isset($formdata->separator)) {
+            $this->separator = $formdata->separator;
+        }
+    }
+
+    function get_export_params() {
+        $params = parent::get_export_params();
+        $params['separator'] = $this->separator;
+        return $params;
+    }
+
+    function print_grades() {
+        global $CFG;
+
+        $export_tracking = $this->track_exports();
+
+        $strgrades = get_string('grades');
+
+        switch ($this->separator) {
+            case 'comma':
+                $separator = ",";
+                break;
+            case 'tab':
+            default:
+                $separator = "\t";
+        }
+
+        /// Print header to force download
+        @header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
+        @header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
+        @header('Pragma: no-cache');
+        header("Content-Type: application/download\n");
+        $downloadfilename = clean_filename("{$this->course->shortname} $strgrades");
+        header("Content-Disposition: attachment; filename=\"$downloadfilename.csv\"");
+
+/// Print names of all the fields
+        echo get_string("idnumber").$separator.
+             get_string("lastname").$separator.
+             get_string("firstname").$separator.
+             get_string("email");
+
+        foreach ($this->columns as $grade_item) {
+            echo $separator.$this->format_column_name($grade_item);
+
+            /// add a feedback column
+            if ($this->export_feedback) {
+                echo $separator.$this->format_column_name($grade_item, true);
+            }
+        }
+        echo "\n";
+
+/// Print all the lines of data.
+        $geub = new grade_export_update_buffer();
+        $gui = new graded_users_iterator($this->course, $this->columns, $this->groupid);
+        $gui->init();
+        while ($userdata = $gui->next_user()) {
+
+            $user = $userdata->user;
+
+            echo $user->idnumber.$separator.$user->lastname.$separator.$user->firstname.$separator.$user->email;
+
+            foreach ($userdata->grades as $itemid => $grade) {
+                if ($export_tracking) {
+                    $status = $geub->track($grade);
+                }
+
+                echo $separator.$this->format_grade($grade);
+
+                if ($this->export_feedback) {
+                    echo $separator.$this->format_feedback($userdata->feedbacks[$itemid]);
+                }
+            }
+            echo "\n";
+        }
+        $gui->close();
+        $geub->close();
+
+        exit;
+    }
+}
+
+?>
Index: grade/report/simple_grader/lib.php
===================================================================
RCS file: grade/report/simple_grader/lib.php
diff -N grade/report/simple_grader/lib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,2247 @@
+<?php // $Id: lib.php,v 1.98.2.43 2008-03-22 20:21:25 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas  http://dougiamas.com     //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ * Date: 05/01/2008
+ * File in which the grader_report class is defined.
+ * @package gradebook
+ */
+
+require_once($CFG->dirroot. '/grade/report/lib.php');
+require_once($CFG->libdir. '/tablelib.php');
+require_once('lib/simple_grade_hook.php');
+
+/**
+ * Class providing an API for the grader report building and displaying.
+ * @uses grade_report
+ * @package gradebook
+ */
+class grade_report_simple_grader extends grade_report {
+
+    /**
+     * The final grades.
+     * @var array $grades
+     */
+    var $grades;
+
+    /**
+     * Array of errors for bulk grades updating.
+     * @var array $gradeserror
+     */
+    var $gradeserror = array();
+
+//// SQL-RELATED
+
+    /**
+     * The id of the grade_item by which this report will be sorted.
+     * @var int $sortitemid
+     */
+    var $sortitemid;
+
+    /**
+     * Sortorder used in the SQL selections.
+     * @var int $sortorder
+     */
+    var $sortorder;
+
+    /**
+     * An SQL fragment affecting the search for users.
+     * @var string $userselect
+     */
+    var $userselect;
+
+    /**
+     * List of collapsed categories from user preference
+     * @var array $collapsed
+     */
+    var $collapsed;
+
+    /**
+     * A count of the rows, used for css classes.
+     * @var int $rowcount
+     */
+    var $rowcount = 0;
+
+    /**
+     * Capability check caching
+     * */
+    var $canviewhidden;
+
+    var $profileid = 0;
+
+    var $anonymous_items = array();
+
+    /**
+     * Constructor. Sets local copies of user preferences and initialises grade_tree.
+     * @param int $courseid
+     * @param object $gpr grade plugin return tracking object
+     * @param string $context
+     * @param int $page The current page being viewed (when report is paged)
+     * @param int $sortitemid The id of the grade_item by which to sort the table
+     */
+    function grade_report_simple_grader($courseid, $gpr, $context, $page=null, $sortitemid=null) {
+        global $CFG;
+        parent::grade_report($courseid, $gpr, $context, $page);
+
+        $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->course->id));
+
+        // load collapsed settings for this report
+        if ($collapsed = get_user_preferences('grade_report_simple_grader_collapsed_categories')) {
+            $this->collapsed = unserialize($collapsed);
+        } else {
+            $this->collapsed = array('aggregatesonly' => array(), 'gradesonly' => array());
+        }
+
+        if (empty($CFG->enableoutcomes)) {
+            $nooutcomes = false;
+        } else {
+            $nooutcomes = get_user_preferences('grade_report_simple_shownooutcomes');
+        }
+
+        // if user report preference set or site report setting set use it, otherwise use course or site setting
+        $switch = $this->get_pref('simple_aggregationposition');
+        if ($switch == '') {
+            $switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
+        }
+
+        // Grab the grade_tree for this course
+        $this->gtree = new grade_tree($this->courseid, true, $switch, $this->collapsed, $nooutcomes);
+
+        $this->sortitemid = $sortitemid;
+
+        // base url for sorting by first/last name
+        $studentsperpage = $this->get_pref('simple_studentsperpage');
+        $perpage = '';
+        $curpage = '';
+
+        if (!empty($studentsperpage)) {
+            $perpage = '&amp;perpage='.$studentsperpage;
+            $curpage = '&amp;page='.$this->page;
+        }
+        $this->baseurl = 'index.php?id='.$this->courseid. $perpage.$curpage.'&amp;';
+
+        $this->pbarurl = 'index.php?id='.$this->courseid.$perpage.'&amp;';
+
+        $this->course->groupmode = 2;
+        $this->setup_groups();
+
+        $this->setup_sortitemid();
+
+        // Get this form's anonymous number profile id, if available
+        $this->setup_anonymous_profile_field();
+    
+    }
+
+    /**
+     * Caches the profileid, to reduce hit to the database 
+     */
+    function setup_anonymous_profile_field() {
+        if (!get_field('block', 'id', 'name', 'anonymous_grade')) {
+            return;
+        }        
+
+        $table = 'block_anonymous_grade_config';
+        if (get_field($table, 'value', 'name', 'enable_features')
+            and $profileid = get_field($table, 'value', 'name', 'profileid')) {
+            $this->profileid = $profileid;
+        }
+    }
+
+    /**
+     * Processes the data sent by the form (grades and feedbacks).
+     * Caller is reposible for all access control checks
+     * @param array $data form submission (with magic quotes)
+     * @return array empty array if success, array of warnings if something fails.
+     */
+    function process_data($data) {
+        $warnings =  process_data($data, $this->courseid);
+        return $warnings;
+    }
+
+    /**
+     * Setting the sort order, this depends on last state
+     * all this should be in the new table class that we might need to use
+     * for displaying grades.
+     */
+    function setup_sortitemid() {
+        global $SESSION;
+
+        if ($this->sortitemid) {
+            if (!isset($SESSION->gradeuserreport->sort)) {
+                if ($this->sortitemid == 'firstname' || $this->sortitemid == 'lastname') {
+                    $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                } else {
+                    $this->sortorder = $SESSION->gradeuserreport->sort = 'DESC';
+                }
+            } else {
+                // this is the first sort, i.e. by last name
+                if (!isset($SESSION->gradeuserreport->sortitemid)) {
+                    if ($this->sortitemid == 'firstname' || $this->sortitemid == 'lastname') {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';    
+                    } else {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'DESC';
+                    }
+                } else if ($SESSION->gradeuserreport->sortitemid == $this->sortitemid) {
+                    // same as last sort
+                    if ($SESSION->gradeuserreport->sort == 'ASC') {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'DESC';
+                    } else {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                    }
+                } else {
+                    if ($this->sortitemid == 'firstname' || $this->sortitemid == 'lastname') {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'ASC';
+                    } else {
+                        $this->sortorder = $SESSION->gradeuserreport->sort = 'DESC';
+                    }
+                }
+            }
+            $SESSION->gradeuserreport->sortitemid = $this->sortitemid;
+        } else {
+            // not requesting sort, use last setting (for paging)
+
+            if (isset($SESSION->gradeuserreport->sortitemid)) {
+                $this->sortitemid = $SESSION->gradeuserreport->sortitemid;
+            }else{
+                $this->sortitemid = 'lastname';
+            }
+
+            if (isset($SESSION->gradeuserreport->sort)) {
+                $this->sortorder = $SESSION->gradeuserreport->sort;
+            } else {
+                $this->sortorder = 'ASC';
+            }
+        }
+    }
+
+    /**
+     * pulls out the userids of the users to be display, and sort them
+     * the right outer join is needed because potentially, it is possible not
+     * to have the corresponding entry in grade_grades table for some users
+     * this is check for user roles because there could be some users with grades
+     * but not supposed to be displayed
+     */
+    function load_users() {
+        global $CFG;
+
+        if (is_numeric($this->sortitemid)) {
+            $sort = "g.finalgrade $this->sortorder";
+
+            $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
+                      FROM {$CFG->prefix}grade_grades g RIGHT OUTER JOIN
+                           {$CFG->prefix}user u ON (u.id = g.userid AND g.itemid = $this->sortitemid)
+                           LEFT JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                           $this->groupsql
+                     WHERE ra.roleid in ($this->gradebookroles)
+                           $this->groupwheresql
+                           AND ra.contextid ".get_related_contexts_string($this->context)."
+                  ORDER BY $sort";
+
+        } else {
+            switch($this->sortitemid) {
+                case 'lastname':
+                    $sort = "u.lastname $this->sortorder, u.firstname $this->sortorder"; break;
+                case 'firstname':
+                    $sort = "u.firstname $this->sortorder, u.lastname $this->sortorder"; break;
+                case 'idnumber':
+                default:
+                    $sort = "u.idnumber $this->sortorder"; break;
+            }
+
+            $sql = "SELECT u.id, u.firstname, u.lastname, u.imagealt, u.picture, u.idnumber
+                      FROM {$CFG->prefix}user u
+                           JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
+                           $this->groupsql
+                     WHERE ra.roleid in ($this->gradebookroles)
+                           $this->groupwheresql
+                           AND ra.contextid ".get_related_contexts_string($this->context)."
+                  ORDER BY $sort";
+        }
+
+
+        $this->users = get_records_sql($sql, $this->get_pref('simple_studentsperpage') * $this->page,
+                            $this->get_pref('simple_studentsperpage'));
+
+        if (empty($this->users)) {
+            $this->userselect = '';
+            $this->users = array();
+        } else {
+            $this->userselect = 'AND g.userid in ('.implode(',', array_keys($this->users)).')';
+        }
+
+        return $this->users;
+    }
+
+    /**
+     * we supply the userids in this query, and get all the grades
+     * pulls out all the grades, this does not need to worry about paging
+    */ 
+    function load_final_grades() {
+        global $CFG;
+
+        // please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
+        $sql = "SELECT g.*
+                  FROM {$CFG->prefix}grade_items gi,
+                       {$CFG->prefix}grade_grades g
+                 WHERE g.itemid = gi.id AND gi.courseid = {$this->courseid} {$this->userselect}";
+
+        $userids = array_keys($this->users);
+
+
+        if ($grades = get_records_sql($sql)) {
+            foreach ($grades as $graderec) {
+                if (in_array($graderec->userid, $userids) and array_key_exists($graderec->itemid, $this->gtree->items)) { // some items may not be present!!
+                    $this->grades[$graderec->userid][$graderec->itemid] = new grade_grade($graderec, false);
+                    $this->grades[$graderec->userid][$graderec->itemid]->grade_item =& $this->gtree->items[$graderec->itemid]; // db caching
+                }
+            }
+        }
+
+        // prefil grades that do not exist yet
+        foreach ($userids as $userid) {
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                if (!isset($this->grades[$userid][$itemid])) {
+                    $this->grades[$userid][$itemid] = new grade_grade();
+                    $this->grades[$userid][$itemid]->itemid = $itemid;
+                    $this->grades[$userid][$itemid]->userid = $userid;
+                    $this->grades[$userid][$itemid]->grade_item =& $this->gtree->items[$itemid]; // db caching
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Builds and returns a div with on/off toggles.
+     * @return string HTML code
+     */
+    function get_toggles_html() {
+        global $CFG, $USER;
+
+        $html = '<div id="grade-report-toggles">';
+        if ($USER->gradeediting[$this->courseid]) {
+            if (has_capability('moodle/grade:manage', $this->context) or has_capability('moodle/grade:hide', $this->context)) {
+                $html .= $this->print_toggle('eyecons', true);
+            }
+            if (has_capability('moodle/grade:manage', $this->context)
+             or has_capability('moodle/grade:lock', $this->context)
+             or has_capability('moodle/grade:unlock', $this->context)) {
+                $html .= $this->print_toggle('locks', true);
+            }
+
+            if (has_capability('moodle/grade:manage', $this->context)) {
+                $html .= $this->print_toggle('quickfeedback', true);
+            }
+
+            /*if (has_capability('moodle/grade:manage', $this->context)) {
+                $html .= $this->print_toggle('calculations', true);
+            }*/
+        }
+
+        
+        if ($this->canviewhidden) {
+            $html .= $this->print_toggle('averages', true);
+        }
+
+        /*if (has_capability('moodle/grade:viewall', $this->context)
+         and has_capability('moodle/site:accessallgroups', $this->context)
+         and $course_has_groups = true) { // TODO replace that last condition with proper check
+            $html .= $this->print_toggle('groups', true);
+        }*/
+
+        $html .= $this->print_toggle('ranges', true);
+        if (!empty($CFG->enableoutcomes)) {
+            $html .= $this->print_toggle('nooutcomes', true);
+        }
+        $html .= '</div>';
+        return $html;
+    }
+
+    /**
+    * Shortcut function for printing the grader report toggles.
+    * @param string $type The type of toggle
+    * @param bool $return Whether to return the HTML string rather than printing it
+    * @return void
+    */
+    function print_toggle($type, $return=false) {
+        global $CFG;
+
+        $icons = array('eyecons' => 't/hide.gif',
+                       'calculations' => 't/calc.gif',
+                       'locks' => 't/lock.gif',
+                       'averages' => 't/mean.gif',
+                       'quickfeedback' => 't/feedback.gif',
+                       'nooutcomes' => 't/outcomes.gif');
+
+        $pref_name = 'grade_report_simple_show' . $type;
+
+        if (array_key_exists($pref_name, $CFG)) {
+            $show_pref = get_user_preferences($pref_name, $CFG->$pref_name);
+        } else {
+            $show_pref = get_user_preferences($pref_name);
+        }
+
+        $strshow = $this->get_lang_string('show' . $type, 'grades');
+        $strhide = $this->get_lang_string('hide' . $type, 'grades');
+
+        $show_hide = 'show';
+        $toggle_action = 1;
+
+        if ($show_pref) {
+            $show_hide = 'hide';
+            $toggle_action = 0;
+        }
+
+        if (array_key_exists($type, $icons)) {
+            $image_name = $icons[$type];
+        } else {
+            $image_name = "t/$type.gif";
+        }
+
+        $string = ${'str' . $show_hide};
+
+        $img = '<img src="'.$CFG->pixpath.'/'.$image_name.'" class="iconsmall" alt="'
+                      .$string.'" title="'.$string.'" />'. "\n";
+
+        $retval = '<div class="gradertoggle">' . $img . '<a href="' . $this->baseurl . "&amp;toggle=$toggle_action&amp;toggle_type=$type\">"
+             . $string . '</a></div>';
+
+        if ($return) {
+            return $retval;
+        } else {
+            echo $retval;
+        }
+    }
+
+    /**
+     * Builds and returns the HTML code for the headers.
+     * @return string $headerhtml
+     */
+    function get_leftheaderhtml() {
+        global $CFG, $USER;
+
+        $strsortasc   = $this->get_lang_string('sortasc', 'grades');
+        $strsortdesc  = $this->get_lang_string('sortdesc', 'grades');
+        $strfirstname = $this->get_lang_string('firstname');
+        $strlastname  = $this->get_lang_string('lastname');
+        $showuseridnumber = $this->get_pref('simple_showuseridnumber');
+
+        if ($this->sortitemid === 'lastname') {
+            if ($this->sortorder == 'ASC') {
+                $lastarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $lastarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $lastarrow = '';
+        }
+
+        if ($this->sortitemid === 'firstname') {
+            if ($this->sortorder == 'ASC') {
+                $firstarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $firstarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $firstarrow = '';
+        }
+        // Prepare Table Headers
+        $headerhtml = '';
+
+        $numrows = count($this->gtree->levels);
+
+        $columns_to_unset = array();
+
+        foreach ($this->gtree->levels as $key=>$row) {
+            $columncount = 0;
+            if ($key == 0) {
+                // do not display course grade category
+                // continue;
+            }
+
+            $headerhtml .= '<tr class="heading name_row">';
+
+            if ($key == $numrows - 1) {
+                $headerhtml .= '<th class="fixedcolumn header c'.$columncount++.'" scope="col"><a href="'.$this->baseurl.'&amp;sortitemid=firstname">'
+                            . $strfirstname . '</a> '
+                            . $firstarrow. '/ <a href="'.$this->baseurl.'&amp;sortitemid=lastname">' . $strlastname . '</a>'. $lastarrow .'</th><th class="fixedcolumn header" c'.$columncount++.'" scope="col"></th>';
+                if ($showuseridnumber) {
+                    if ('idnumber' == $this->sortitemid) {
+                        if ($this->sortorder == 'ASC') {
+                            $idnumberarrow = print_arrow('up', $strsortasc, true);
+                        } else {
+                            $idnumberarrow = print_arrow('down', $strsortdesc, true);
+                        }
+                    } else {
+                        $idnumberarrow = '';
+                    }
+                    $headerhtml .= '<th class="fixedcolumn header c'.$columncount++.' useridnumber" scope="col"><a href="'.$this->baseurl.'&amp;sortitemid=idnumber">'
+                            . get_string('idnumber') . '</a> ' . $idnumberarrow . '</th>';
+                }
+             } else {
+                $colspan='colspan="2"';
+                if ($showuseridnumber) {
+                    $colspan = 'colspan="3" ';
+                }
+
+                $headerhtml .= '<td '.$colspan.'class=" fixedcolumn cell c'.$columncount++.' topleft">&nbsp;</td>';
+
+                if ($showuseridnumber) {
+                    $columncount++;
+                }
+            }
+
+            $headerhtml .= '</tr>';
+        }
+        return $headerhtml;
+    }
+
+    /**
+     * Builds and return the HTML rows of the table (grades headed by student).
+     * @return string HTML
+     */
+    function get_leftstudentshtml() {
+        global $CFG, $USER;
+
+        $studentshtml = '';
+        $showuserimage = $this->get_pref('simple_showuserimage');
+        $showuseridnumber = $this->get_pref('simple_showuseridnumber');
+        $numusers      = count($this->users);
+
+        // Preload scale objects for items with a scaleid
+        $row_classes = array(' even ', ' odd ');
+
+        foreach ($this->users as $userid => $user) {
+
+            if ($this->canviewhidden) {
+                $altered = array();
+                $unknown = array();
+            } else {
+                $hiding_affected = grade_grade::get_hiding_affected($this->grades[$userid], $this->gtree->items);
+                $altered = $hiding_affected['altered'];
+                $unknown = $hiding_affected['unknown'];
+                unset($hiding_affected);
+            }
+
+            $columncount = 0;
+            // Student name and link
+            $user_pic = null;
+            if ($showuserimage) {
+                $user_pic = '<div class="userpic">'. custom_user_image($user) . '</div>';
+	        }
+            $studentshtml .= '<tr class="r'.$this->rowcount++ . $row_classes[$this->rowcount % 2] . '">'
+                          .'<th class="fixedcolumn header c'.$columncount++.' user" scope="row" onclick="set_row(this.parentNode.rowIndex);">'.$user_pic.'</a>
+				<a href="'.$CFG->wwwroot.'/course/user.php?id='.$this->course->id.'&amp;user='.$user->id.'&amp;mode=grade" target="_blank">'.fullname($user).'</a></th>
+                                <th class="fixedcolumn header c'.$columncount++.' user"><a href="quick_edit.php?id='.$this->courseid.
+                                '&amp;mode=user&amp;itemid='.$user->id.'">'.get_string('quick_edit', 'gradereport_simple_grader').'</a>';
+            $studentshtml .= "</th>";
+            
+            if ($showuseridnumber) {
+                $studentshtml .= '<th class="fixedcolumn header c'.$columncount++.' useridnumber" onclick="set_row(this.parentNode.rowIndex);">'.
+                        $user->idnumber.'</a></th>';
+            }
+
+            $studentshtml .= '</tr>';
+        }
+        return $studentshtml;
+    }
+
+    /**
+     * Builds and return the HTML row of column totals.
+     * @param  bool $grouponly Whether to return only group averages or all averages.
+     * @return string HTML
+     */
+    function get_leftavghtml($grouponly=false) {
+        global $CFG, $USER;
+
+        if (!$this->canviewhidden) {
+            // totals might be affected by hiding, if user can not see hidden grades the aggregations might be altered
+            // better not show them at all if user can not see all hideen grades
+            return;
+        }
+
+        $averagesdisplaytype   = $this->get_pref('simple_averagesdisplaytype');
+        $averagesdecimalpoints = $this->get_pref('simple_averagesdecimalpoints');
+        $meanselection         = $this->get_pref('simple_meanselection');
+        $shownumberofgrades    = $this->get_pref('simple_shownumberofgrades');
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $avghtml = '';
+        $avgcssclass = 'avg';
+
+        if ($grouponly) {
+            $straverage = get_string('groupavg', 'grades');
+            $showaverages = $this->currentgroup;
+            $groupsql = $this->groupsql;
+            $groupwheresql = $this->groupwheresql;
+            $avgcssclass = 'groupavg';
+        } else {
+            $straverage = get_string('overallaverage', 'grades');
+            $showaverages = $this->get_pref('simple_showaverages');
+            $groupsql = "";
+            $groupwheresql = "";
+        }
+
+/*        if ($shownumberofgrades) {
+            $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
+        }
+
+        $totalcount = $this->get_numusers($grouponly);
+*/
+        if ($showaverages) {
+            $columncount=0;
+            $colspan='colspan="2"';
+            if ($showuseridnumber) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $avghtml = '<tr class="' . $avgcssclass . ' r'.$this->rowcount++.'"><th class="fixedcolumn header c0" '.$colspan.'scope="row">'.$straverage.'</th>';
+
+            if ($showuseridnumber) {
+                $columncount++;
+            }
+            $avghtml .= '</tr>';
+        }
+        return $avghtml;
+    }
+
+    /**
+     * Builds and return the HTML row of ranges for each column (i.e. range).
+     * @return string HTML
+     */
+    function get_leftrangehtml() {
+        global $USER;
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $scalehtml = '';
+        if ($this->get_pref('simple_showranges')) {
+            $rangesdisplaytype   = $this->get_pref('simple_rangesdisplaytype');
+            $rangesdecimalpoints = $this->get_pref('simple_rangesdecimalpoints');
+
+            $colspan='colspan="2"';
+            if ($showuseridnumber) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $scalehtml = '<tr class="range_row">'
+                       . '<th class="fixedcolumn header c0 range" '.$colspan.'scope="row">'.$this->get_lang_string('range','grades').'</th>';
+
+            $scalehtml .= '</tr>';
+        }
+        return $scalehtml;
+    }
+
+    /**
+     * Builds and return the HTML row of Control Icons for each column (i.e. controls).
+     * @return string HTML
+     */
+    function get_lefticonshtml() {
+        global $USER;
+
+        $iconshtml = '';
+        if ($USER->gradeediting[$this->courseid]) {
+
+            $colspan='colspan="2"';
+            if ($this->get_pref('simple_showuseridnumber')) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $iconshtml = '<tr class="controls_row">'
+                       . '<th class="header c0 range" scope="row" '.$colspan.'>'.$this->get_lang_string('controls','grades').'</th>';
+
+        }
+        return $iconshtml;
+    }
+
+    
+    /**
+     * Given a grade_category, grade_item or grade_grade, this function
+     * figures out the state of the object and builds then returns a div
+     * with the icons needed for the grader report.
+     *
+     * @param object $object
+     * @return string HTML
+     */
+    function get_icons($element) {
+        global $CFG, $USER;
+
+        if (!$USER->gradeediting[$this->courseid]) {
+            return '<div class="grade_icons" />';
+        }
+
+        $icons = str_replace('/edit/tree/', '/edit/simple_tree/', $this->gtree->get_edit_icon($element, $this->gpr));
+
+        // Init all icons
+        $edit_icon             = $this->gtree->get_edit_icon($element, $this->gpr);
+        $edit_calculation_icon = '';
+        $show_hide_icon        = '';
+        $lock_unlock_icon      = '';
+
+        if (has_capability('moodle/grade:manage', $this->context)) {
+
+            if ($this->get_pref('simple_showeyecons')) {
+               $show_hide_icon = $this->gtree->get_hiding_icon($element, $this->gpr);
+            }
+
+            if ($this->get_pref('simple_showlocks')) {
+                $lock_unlock_icon = $this->gtree->get_locking_icon($element, $this->gpr);
+            }
+        }
+
+        return '<div class="grade_icons">'.$icons.$edit_calculation_icon.$show_hide_icon.$lock_unlock_icon.'</div>';
+    }
+
+    /**
+     * Given a category element returns collapsing +/- icon if available
+     * @param object $object
+     * @return string HTML
+     */
+    function get_collapsing_icon($element) {
+        global $CFG;
+
+        $contract_expand_icon = '';
+        // If object is a category, display expand/contract icon
+        if ($element['type'] == 'category') {
+            // Load language strings
+            $strswitch_minus = $this->get_lang_string('aggregatesonly', 'grades');
+            $strswitch_plus  = $this->get_lang_string('gradesonly', 'grades');
+            $strswitch_whole = $this->get_lang_string('fullmode', 'grades');
+
+            $expand_contract = 'switch_minus'; // Default: expanded
+            // $this->get_pref('aggregationview', $element['object']->id) == GRADE_REPORT_AGGREGATION_VIEW_COMPACT
+
+            if (in_array($element['object']->id, $this->collapsed['aggregatesonly'])) {
+                $expand_contract = 'switch_plus';
+            } elseif (in_array($element['object']->id, $this->collapsed['gradesonly'])) {
+                $expand_contract = 'switch_whole';
+            }
+            $url = $this->gpr->get_return_url(null, array('target'=>$element['eid'], 'action'=>$expand_contract, 'sesskey'=>sesskey()));
+            $contract_expand_icon = '<a href="'.$url.'"><img src="'.$CFG->pixpath.'/t/'.$expand_contract.'.gif" class="iconsmall" alt="'
+                                    .${'str'.$expand_contract}.'" title="'.${'str'.$expand_contract}.'" /></a>';
+        }
+        return $contract_expand_icon;
+    }
+
+    /**
+     * Processes a single action against a category, grade_item or grade.
+     * @param string $target eid ({type}{id}, e.g. c4 for category4)
+     * @param string $action Which action to take (edit, delete etc...)
+     * @return
+     */
+    function process_action($target, $action) {
+        // TODO: this code should be in some grade_tree static method
+        $targettype = substr($target, 0, 1);
+        $targetid = substr($target, 1);
+        // TODO: end
+
+        if ($collapsed = get_user_preferences('grade_report_simple_grader_collapsed_categories')) {
+            $collapsed = unserialize($collapsed);
+        } else {
+            $collapsed = array('aggregatesonly' => array(), 'gradesonly' => array());
+        }
+
+        switch ($action) {
+            case 'switch_minus': // Add category to array of aggregatesonly
+                if (!in_array($targetid, $collapsed['aggregatesonly'])) {
+                    $collapsed['aggregatesonly'][] = $targetid;
+                    set_user_preference('grade_report_simple_grader_collapsed_categories', serialize($collapsed));
+                }
+                break;
+
+            case 'switch_plus': // Remove category from array of aggregatesonly, and add it to array of gradesonly
+                $key = array_search($targetid, $collapsed['aggregatesonly']);
+                if ($key !== false) {
+                    unset($collapsed['aggregatesonly'][$key]);
+                }
+                if (!in_array($targetid, $collapsed['gradesonly'])) {
+                    $collapsed['gradesonly'][] = $targetid;
+                }
+                set_user_preference('grade_report_simple_grader_collapsed_categories', serialize($collapsed));
+                break;
+            case 'switch_whole': // Remove the category from the array of collapsed cats
+                $key = array_search($targetid, $collapsed['gradesonly']);
+                if ($key !== false) {
+                    unset($collapsed['gradesonly'][$key]);
+                    set_user_preference('grade_report_simple_grader_collapsed_categories', serialize($collapsed));
+                }
+
+                break;
+            default:
+                break;
+        }
+
+        return true;
+    }
+
+    /**
+     * Builds and returns the HTML code for the headers.
+     * @return string $headerhtml
+     */
+    function get_rightheaderhtml() {
+        global $CFG, $USER;
+
+        $strsortasc   = $this->get_lang_string('sortasc', 'grades');
+        $strsortdesc  = $this->get_lang_string('sortdesc', 'grades');
+        $showuseridnumber = $this->get_pref('simple_showuseridnumber');
+
+
+        if ($this->sortitemid === 'lastname') {
+            if ($this->sortorder == 'ASC') {
+                $lastarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $lastarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $lastarrow = '';
+        }
+
+        if ($this->sortitemid === 'firstname') {
+            if ($this->sortorder == 'ASC') {
+                $firstarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $firstarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $firstarrow = '';
+        }
+
+        // Prepare Table Headers
+        $headerhtml = '';
+
+        $numrows = count($this->gtree->levels);
+
+        $columns_to_unset = array();
+
+
+        foreach ($this->gtree->levels as $key=>$row) {
+            $columncount = 0;
+            if ($key == 0) {
+                // do not display course grade category
+                // continue;
+            }
+
+            $headerhtml .= '<tr class="heading name_row">';
+
+            foreach ($row as $columnkey => $element) {
+		$quickeditlink = '';
+                $sort_link = '';
+                if (isset($element['object']->id)) {
+                    $sort_link = $this->baseurl.'&amp;sortitemid=' . $element['object']->id;
+                }
+
+                $eid    = $element['eid'];
+                $object = $element['object'];
+                $type   = $element['type'];
+                $categorystate = @$element['categorystate'];
+                $itemmodule = null;
+                $iteminstance = null;
+
+                $columnclass = 'c' . $columncount++;
+                if (!empty($element['colspan'])) {
+                    $colspan = 'colspan="'.$element['colspan'].'"';
+                    $columnclass = '';
+                } else {
+                    $colspan = '';
+                }
+
+                if (!empty($element['depth'])) {
+                    $catlevel = ' catlevel'.$element['depth'];
+                } else {
+                    $catlevel = '';
+                }
+
+// Element is a filler
+                if ($type == 'filler' or $type == 'fillerfirst' or $type == 'fillerlast') {
+                    $headerhtml .= '<th class="'.$columnclass.' '.$type.$catlevel.'" '.$colspan.' scope="col">&nbsp;</th>';
+                }
+// Element is a category
+                else if ($type == 'category') {
+                    $parent_category = $object->get_parent_category();
+                    
+                    if ($parent_category) {
+                        $course_weight_total = $this->get_total_weights($parent_category);
+                    }
+                
+                    $headerhtml .= '<th class="header '. $columnclass.' category'.$catlevel.'" '.$colspan.' scope="col">'
+                                . shorten_text($element['object']->get_name());
+                    if ($object->grade_item->itemtype == 'category' 
+                        && $parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                        $weight = format_float($object->grade_item->aggregationcoef, 2); 
+                        $headerhtml .= ': '.$weight .' (<span class="gradeweight">' . 
+                            format_float(($weight/$course_weight_total) * 100, 2) . 
+                            '%</span>)' .' ';
+                    }
+                    $headerhtml .=  $this->get_collapsing_icon($element);
+
+                    // Print icons
+                    if ($USER->gradeediting[$this->courseid]) {
+                        $headerhtml .= $this->get_icons($element);
+                    }
+
+                    $headerhtml .= '</th>';
+                }
+// Element is a grade_item
+                else {
+                    $itemmodule = $element['object']->itemmodule;
+                    $iteminstance = $element['object']->iteminstance;
+
+                    if ($element['object']->id == $this->sortitemid) {
+                        if ($this->sortorder == 'ASC') {
+                            $arrow = $this->get_sort_arrow('up', $sort_link);
+                        } else {
+                            $arrow = $this->get_sort_arrow('down', $sort_link);
+                        }
+                    } else {
+                        $arrow = $this->get_sort_arrow('move', $sort_link);
+                    }
+
+                    $hidden = '';
+                    if ($element['object']->is_hidden()) {
+                        $hidden = ' hidden ';
+                    }
+        		    $headerhtml .= '<th class="header '.$columnclass.' '.$type.$catlevel.$hidden.'" scope="col" onclick="set_col(this.cellIndex)">';
+        		    if(!$object->is_course_item() && !$object->is_category_item()) {
+                        $endurl = '';
+                        if ($this->profileid && $anonymous = get_record('block_anon_grade_items', 'itemid', $object->id)) {
+                            $this->anonymous_items[$object->id] = $anonymous->completed;
+                        }
+
+                        if ($this->profileid && $anonymous && !$anonymous->completed){
+                            $endurl = '&amp;mode=anonymous&amp;fieldid='. $this->profileid . '">';
+                        }
+                        else {
+                            $endurl = '&amp;mode=grades&amp;group='.$this->currentgroup.'">';
+                        }
+                        $quickeditlink .= '<a class="quickedit" href="quick_edit.php?id='.$this->courseid.'&amp;itemid='.
+                            $element['object']->id. $endurl . get_string('quick_edit', 'gradereport_simple_grader').'</a>';
+                    }
+                    $headerlink = $this->gtree->get_element_header($element, true, $this->get_pref('simple_showactivityicons'), false);
+                    $headerhtml .= shorten_text($headerlink) . $arrow;
+                    $headerhtml .= $quickeditlink;
+        		    $headerhtml .= '</th>';
+                }
+
+            }
+
+            $headerhtml .= '</tr>';
+        }
+        return $headerhtml;
+    }
+
+    /**
+     * Builds and return the HTML rows of the table (grades headed by student).
+     * @return string HTML
+     */
+    function get_rightstudentshtml() {
+        global $CFG, $USER;
+
+        $studentshtml = '';
+        $strfeedback  = $this->get_lang_string("feedback");
+        $strgrade     = $this->get_lang_string('grade');
+        $gradetabindex = 1;
+        $numusers      = count($this->users);
+
+        // Preload scale objects for items with a scaleid
+        $scales_list = '';
+        $tabindices = array();
+
+        foreach ($this->gtree->items as $item) {
+            if (!empty($item->scaleid)) {
+                $scales_list .= "$item->scaleid,";
+            }
+
+            $tabindices[$item->id]['grade'] = $gradetabindex;
+            $tabindices[$item->id]['feedback'] = $gradetabindex + $numusers;
+            $gradetabindex += $numusers * 2;
+        }
+        $scales_array = array();
+
+        if (!empty($scales_list)) {
+            $scales_list = substr($scales_list, 0, -1);
+            $scales_array = get_records_list('scale', 'id', $scales_list);
+        }
+        
+        $row_classes = array(' even ', ' odd ');
+
+        $row_classes = array(' even ', ' odd ');
+
+        foreach ($this->users as $userid => $user) {
+
+            if ($this->canviewhidden) {
+                $altered = array();
+                $unknown = array();
+            } else {
+                $hiding_affected = grade_grade::get_hiding_affected($this->grades[$userid], $this->gtree->items);
+                $altered = $hiding_affected['altered'];
+                $unknown = $hiding_affected['unknown'];
+                unset($hiding_affected);
+            }
+
+            $columncount = 0;
+ 		$studentshtml .= '<tr class="r'.$this->rowcount++ . $row_classes[$this->rowcount % 2] . '">';
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+                $grade = $this->grades[$userid][$item->id];
+
+                // Get the decimal points preference for this item
+                $decimalpoints = $item->get_decimals();
+
+                if (in_array($itemid, $unknown)) {
+                    $gradeval = null;
+                } else if (array_key_exists($itemid, $altered)) {
+                    $gradeval = $altered[$itemid];
+                } else {
+                    $gradeval = $grade->finalgrade;
+                }
+
+                // MDL-11274
+                // Hide grades in the grader report if the current grader doesn't have 'moodle/grade:viewhidden'
+                if (!$this->canviewhidden and $grade->is_hidden()) {
+                    if (!empty($CFG->grade_hiddenasdate) and $grade->get_datesubmitted() and !$item->is_category_item() and !$item->is_course_item()) {
+                        // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
+                        $studentshtml .= '<td class="cell c'.$columncount++.'"><span class="datesubmitted">'.userdate($grade->get_datesubmitted(),get_string('strftimedatetimeshort')).'</span></td>';
+                    } else {
+                        $studentshtml .= '<td class="cell c'.$columncount++.'">-</td>';
+                    }
+                    continue;
+                }
+
+                // emulate grade element
+                $eid = $this->gtree->get_grade_eid($grade);
+                $element = array('eid'=>$eid, 'object'=>$grade, 'type'=>'grade');
+                $anonymous_item = array_key_exists($item->id, $this->anonymous_items);
+
+                $cellclasses = 'cell c'.$columncount++;
+                if ($item->is_category_item()) {
+                    $cellclasses .= ' cat';
+                }
+                if ($item->is_course_item()) {
+                    $cellclasses .= ' course';
+                }
+                if ($grade->is_overridden()) {
+                    $cellclasses .= ' overridden';
+                }
+
+                if ($grade->is_excluded()) {
+                    $cellclasses .= ' excluded';
+                }
+
+                $studentshtml .= '<td class="'.$cellclasses.'">';
+
+                if ($grade->is_excluded()) {
+                    $studentshtml .= '<span class="excludedfloater">' . get_string('excluded', 'grades') . '</span>' . ' ';
+                }
+
+                // Do not show any icons if no grade (no record in DB to match)
+//-------------------------- Changed that ion print out for course categories --------------------------//
+                if (!$item->needsupdate and $USER->gradeediting[$this->courseid] and !$item->is_category_item() 
+                    and !$item->is_course_item() and !$anonymous_item){
+                    $studentshtml .= $this->get_icons($element);
+                }
+
+                $hidden = '';
+                if ($grade->is_hidden()) {
+                    $hidden = ' hidden ';
+                }
+
+                $gradepass = ' gradefail '; 
+                if ($grade->is_passed($item)) {
+                    $gradepass = ' gradepass ';
+                } elseif (is_null($grade->is_passed($item))) {
+                    $gradepass = '';
+                }
+
+                // if in editting mode, we need to print either a text box
+                // or a drop down (for scales)
+                // grades in item of type grade category or course are not directly editable
+                if ($item->needsupdate) {
+                    $studentshtml .= '<span class="gradingerror'.$hidden.'">'.get_string('error').'</span>';
+
+                } else if ($USER->gradeediting[$this->courseid]) {
+                    // Changed for multiplicator
+                    $gradeval = ($item->itemtype == 'manual') ? $grade->rawgrade : $grade->finalgrade;
+                    // End change
+
+                    if ($item->scaleid && !empty($scales_array[$item->scaleid])) {
+                        $scale = $scales_array[$item->scaleid];
+                        $gradeval = (int)$gradeval; // scales use only integers
+                        $scales = explode(",", $scale->scale);
+                        // reindex because scale is off 1
+
+                        // MDL-12104 some previous scales might have taken up part of the array
+                        // so this needs to be reset
+                        $scaleopt = array();
+                        $i = 0;
+                        foreach ($scales as $scaleoption) {
+                            $i++;
+                            $scaleopt[$i] = $scaleoption;
+                        }
+
+                        //Removed because it was confusing for teachers
+                        if (/*$this->get_pref('simple_quickgrading') and*/ $grade->is_editable() && !$item->is_course_item()) {
+                            $oldval = empty($gradeval) ? -1 : $gradeval;
+                            if (empty($item->outcomeid)) {
+                                $nogradestr = $this->get_lang_string('nograde');
+                            } else {
+                                $nogradestr = $this->get_lang_string('nooutcome', 'grades');
+                            }
+                            $studentshtml .= '<input id="oldgrade_'.$userid.'_'.$item->id.'" type="hidden" name="oldgrade_'.
+                                          $userid.'_'.$item->id.'" value="'.$oldval.'"/>';
+                            $studentshtml .= choose_from_menu($scaleopt, 'grade_'.$userid.'_'.$item->id,
+                                                              $gradeval, $nogradestr, '', '-1',
+                                                              true, false, $tabindices[$item->id]['grade']);
+                        } elseif(!empty($scale)) {
+                            $scales = explode(",", $scale->scale);
+
+                            // invalid grade if gradeval < 1
+                            if ($gradeval < 1) {
+                                $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">-</span>';
+                            } else {
+                                $gradeval = (int)bounded_number($grade->grade_item->grademin, $gradeval, $grade->grade_item->grademax); //just in case somebody changes scale
+                                $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.$scales[$gradeval-1].'</span>';
+                            }
+                        } else {
+                            // no such scale, throw error?
+                        }
+
+                    } else if ($item->gradetype != GRADE_TYPE_TEXT) { // Value type
+//-------------------------- Changed: we just print out categories -------------------------------//
+                        if ($item->is_course_item() or $item->is_category_item() or $anonymous_item) {
+                            $gradedisplaytype = $item->get_displaytype();
+                            $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.simple_grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null).'</span>';                        
+                        } else if (!empty($this->anonymous_items[$item->id])) {
+                            $studentshtml .= '<span class="gradevalue'. $hidden. '">-</span>';
+                        }
+                        // Removed this feature because it was confusing to teachers 
+                        else if (/*$this->get_pref('quickgrading') and*/ $grade->is_editable()) {
+                            $value = format_float($gradeval, $decimalpoints);
+                            $studentshtml .= '<input id="oldgrade_'.$userid.'_'.$item->id.'" type="hidden" name="oldgrade_'.
+                                            $userid.'_'.$item->id.'" value="'.$value.'" />';
+                            $studentshtml .= '<input id="grade_'.$userid.'_'.$item->id.'" size="6" tabindex="' . 
+                                            $tabindices[$item->id]['grade'] . '" type="text" title="'. 
+                                            $strgrade .'" name="grade_'.$userid.'_' .$item->id.'" value="'.$value.'" />';
+                        } else {
+                            $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.format_float($gradeval, $decimalpoints).'</span>';
+                        }
+                    }
+
+
+                    // If quickfeedback is on, print an input element
+                    if ($this->get_pref('simple_showquickfeedback') and $grade->is_editable() and $item->itemtype != 'anonymous') {
+                        /*
+                        Removed because it was confusing to teachers
+                        if ($this->get_pref('simple_quickgrading')) {
+                        }*/
+                        $studentshtml .= '<input id="oldfeedback_'.$userid.'_'.$item->id.'" type="hidden" name="oldfeedback_'
+                                      .$userid.'_'.$item->id.'" value="' . s($grade->feedback) . '" />';
+                        $studentshtml .= '<input id="feedback_'.$userid.'_'.$item->id.'" class="quickfeedback" tabindex="' 
+                                      .$tabindices[$item->id]['feedback'] . '" size="6" title="' . $strfeedback 
+                                      .'" type="text" name="feedback_'.$userid.'_'.$item->id.'" value="' . s($grade->feedback) . '" />';
+                    }
+
+                } else { // Not editing
+                    $gradedisplaytype = $item->get_displaytype();
+
+                    // If feedback present, surround grade with feedback tooltip: Open span here
+                    if (!empty($grade->feedback)) {
+                        $overlib = '';
+                        $feedback = addslashes_js(trim(format_string($grade->feedback, $grade->feedbackformat)));
+                        $overlib = "return overlib('$feedback', BORDER, 0, FGCLASS, 'feedback', "
+                                  ."CAPTIONFONTCLASS, 'caption', CAPTION, '$strfeedback');";
+                        $studentshtml .= '<span onmouseover="'.s($overlib).'" onmouseout="return nd();">';
+                    }
+
+                    $gradedisplay = ($item->itemtype == 'anonymous') ? '-' : simple_grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null);
+
+                    if ($item->needsupdate) {
+                        $studentshtml .= '<span class="gradingerror'.$hidden.$gradepass.'">'.get_string('error').'</span>';
+                    } else {
+                        $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'. $gradedisplay .'</span>';
+                    }
+
+                    // Close feedback span
+                    if (!empty($grade->feedback)) {
+                        $studentshtml .= '</span>';
+                    }
+                }
+
+                if (!empty($this->gradeserror[$item->id][$userid])) {
+                    $studentshtml .= $this->gradeserror[$item->id][$userid];
+                }
+
+                $studentshtml .=  '</td>' . "\n";
+            }
+            $studentshtml .= '</tr>';
+        }
+        return $studentshtml;
+    }
+
+    /**
+     * Builds and return the HTML row of column totals.
+     * @param  bool $grouponly Whether to return only group averages or all averages.
+     * @return string HTML
+     */
+    function get_rightavghtml($grouponly=false) {
+        global $CFG, $USER;
+
+        if (!$this->canviewhidden) {
+            // totals might be affected by hiding, if user can not see hidden grades the aggregations might be altered
+            // better not show them at all if user can not see all hideen grades
+            return;
+        }
+
+        $averagesdisplaytype   = $this->get_pref('simple_averagesdisplaytype');
+        $averagesdecimalpoints = $this->get_pref('simple_averagesdecimalpoints');
+        $meanselection         = $this->get_pref('simple_meanselection');
+        $shownumberofgrades    = $this->get_pref('simple_shownumberofgrades');
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $avghtml = '';
+        $avgcssclass = 'avg';
+
+        if ($grouponly) {
+            $straverage = get_string('groupavg', 'grades');
+            $showaverages = $this->currentgroup;
+            $groupsql = $this->groupsql;
+            $groupwheresql = $this->groupwheresql;
+            $avgcssclass = 'groupavg';
+        } else {
+            $straverage = get_string('overallaverage', 'grades');
+            $showaverages = $this->get_pref('simple_showaverages');
+            $groupsql = "";
+            $groupwheresql = "";
+        }
+
+        if ($shownumberofgrades) {
+            $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
+        }
+
+        $totalcount = $this->get_numusers($grouponly);
+
+        if ($showaverages) {
+
+            // find sums of all grade items in course
+            /*
+                New Query fixes the situation where there could be the same person in
+                multiple graded roles
+            */
+            $SQL = "SELECT DISTINCT (
+                    g.itemid
+                    ), SUM( g.finalgrade ) AS sum
+                    FROM {$CFG->prefix}grade_items gi
+                    JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
+                    JOIN {$CFG->prefix}user u ON g.userid = u.id
+                    JOIN (
+                    SELECT DISTINCT (ra.userid)
+                    FROM {$CFG->prefix}role_assignments ra
+                    WHERE ra.roleid IN ($this->gradebookroles)
+                        AND ra.contextid ".get_related_contexts_string($this->context)."
+                    ) AS sub ON sub.userid = u.id
+                    $groupsql
+                    WHERE gi.courseid= $this->courseid
+                    AND g.finalgrade IS NOT NULL
+                    $groupwheresql
+                    GROUP BY g.itemid";
+
+            /*$SQL = "SELECT g.itemid, SUM(g.finalgrade) AS sum
+                      FROM {$CFG->prefix}grade_items gi
+                           JOIN {$CFG->prefix}grade_grades g      ON g.itemid = gi.id 
+                           JOIN {$CFG->prefix}user u              ON u.id = g.userid 
+                           JOIN {$CFG->prefix}role_assignments ra ON ra.userid = u.id
+                           $groupsql
+                     WHERE gi.courseid = $this->courseid
+                           AND (SELECT DISTINCT ra.roleid in ($this->gradebookroles))
+                           AND ra.contextid ".get_related_contexts_string($this->context)."
+                           AND g.finalgrade IS NOT NULL
+                           $groupwheresql
+                  GROUP BY g.itemid";*/
+            $sum_array = array();
+            if ($sums = get_records_sql($SQL)) {
+                foreach ($sums as $itemid => $csum) {
+                    $sum_array[$itemid] = $csum->sum;
+                }
+            }
+
+
+            $columncount=0;
+
+
+            $avghtml = '<tr class="' . $avgcssclass . ' r'.$this->rowcount++.'">';
+
+            // MDL-10875 Empty grades must be evaluated as grademin, NOT always 0
+            // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
+          
+            /*
+                Changed the query to support people in multiple roles; By doing it this way, we get the 
+                total number of graded items, instead of ungraded items
+             */ 
+            $SQL = "SELECT DISTINCT (gi.id), COUNT(u.id) AS count
+                        FROM {$CFG->prefix}grade_items gi
+                        JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
+                        JOIN {$CFG->prefix}user u ON u.id = g.userid
+                        JOIN (SELECT DISTINCT (ra.userid)
+                                FROM {$CFG->prefix}role_assignments ra
+                                WHERE ra.roleid IN ($this->gradebookroles)
+                                  AND ra.contextid ".get_related_contexts_string($this->context)."
+                             ) AS sub ON sub.userid = u.id
+                        $groupsql
+                        WHERE gi.courseid = $this->courseid
+                        AND g.finalgrade IS NOT NULL
+                        $groupwheresql
+                        GROUP BY g.itemid";
+ 
+            /*$SQL = "SELECT gi.id, COUNT(u.id) AS count
+                      FROM {$CFG->prefix}grade_items gi
+                           CROSS JOIN {$CFG->prefix}user u
+                           JOIN {$CFG->prefix}role_assignments ra        ON ra.userid = u.id
+                           LEFT OUTER JOIN  {$CFG->prefix}grade_grades g ON (g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL) 
+                           $groupsql
+                     WHERE gi.courseid = $this->courseid
+                           AND (SELECT DISTINCT ra.roleid in ($this->gradebookroles))
+                           AND ra.contextid ".get_related_contexts_string($this->context)."
+                           AND g.id IS NULL
+                           $groupwheresql
+                  GROUP BY gi.id";*/
+            
+            $ungraded_counts = get_records_sql($SQL);
+
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+
+                if ($item->needsupdate) {
+                    $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
+                    continue;
+                }
+
+                if (!isset($sum_array[$item->id])) {
+                    $sum_array[$item->id] = 0;
+                }
+
+                if (empty($ungraded_counts[$itemid])) {
+                    $ungraded_count = 0;
+                } else {
+                    $ungraded_count = $ungraded_counts[$itemid]->count;
+                }
+
+                if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
+                    $mean_count = /*$totalcount - */ $ungraded_count;
+                } else { // Bump up the sum by the number of ungraded items * grademin
+                    $sum_array[$item->id] += $ungraded_count * $item->grademin;
+                    $mean_count = $totalcount;
+                }
+
+                $decimalpoints = $item->get_decimals();
+
+                // Determine which display type to use for this average
+                if ($USER->gradeediting[$this->courseid]) {
+                    $displaytype = GRADE_DISPLAY_TYPE_REAL;
+
+                } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
+                    $displaytype = $item->get_displaytype();
+
+                } else {
+                    $displaytype = $averagesdisplaytype;
+                }
+
+                // Override grade_item setting if a display preference (not inherit) was set for the averages
+                if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
+                    $decimalpoints = $item->get_decimals();
+
+                } else {
+                    $decimalpoints = $averagesdecimalpoints;
+                }
+
+                if (!isset($sum_array[$item->id]) || $mean_count == 0) {
+                    $avghtml .= '<td class="cell c' . $columncount++.'">-</td>';
+                } else {
+                    $sum = $sum_array[$item->id];
+                    $avgradeval = $sum/$mean_count;
+                    $gradehtml = simple_grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
+
+                    $numberofgrades = '';
+                    if ($shownumberofgrades) {
+                        $numberofgrades = " ($mean_count)";
+                    }
+
+                    $avghtml .= '<td class="cell c' . $columncount++.'">'.$gradehtml.$numberofgrades.'</td>';
+                }
+            }
+            $avghtml .= '</tr>';
+        }
+        return $avghtml;
+    }
+
+    /**
+     * Builds and return the HTML row of ranges for each column (i.e. range).
+     * @return string HTML
+     */
+    function get_rightrangehtml() {
+        global $USER;
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $scalehtml = '';
+        if ($this->get_pref('simple_showranges')) {
+            $rangesdisplaytype   = $this->get_pref('simple_rangesdisplaytype');
+            $rangesdecimalpoints = $this->get_pref('simple_rangesdecimalpoints');
+
+            $columncount=0;
+            $scalehtml = '<tr class="range_row">';
+
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+
+                // Determine which display type to use for this average
+                if ($USER->gradeediting[$this->courseid]) {
+                    $displaytype = GRADE_DISPLAY_TYPE_REAL;
+
+                } else if ($rangesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave report and user prefs
+                    $displaytype = $item->get_displaytype();
+
+                } else {
+                    $displaytype = $rangesdisplaytype;
+                }
+
+                // Override grade_item setting if a display preference (not default) was set for the averages
+                if ($rangesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
+                    $decimalpoints = $item->get_decimals();
+
+                } else {
+                    $decimalpoints = $rangesdecimalpoints;
+                }
+
+                if ($displaytype == GRADE_DISPLAY_TYPE_PERCENTAGE) {
+                    $grademin = "0 %";
+                    $grademax = "100 %";
+
+                } else {
+                    $grademin = simple_grade_format_gradevalue($item->grademin, $item, true, $displaytype, $decimalpoints);
+                    $grademax = simple_grade_format_gradevalue($item->grademax, $item, true, $displaytype, $decimalpoints);
+                }
+
+                $hidden = '';
+                if ($item->is_hidden()) {
+                    $hidden = ' hidden ';
+                }
+
+                $scalehtml .= '<th class="header c'.$columncount++.' range"><span class="rangevalues'.$hidden.'">'. $grademin.'&ndash;'. $grademax.'</span></th>';
+            }
+            $scalehtml .= '</tr>';
+        }
+        return $scalehtml;
+    }
+    
+    /**
+     * Builds and return the HTML row of Control Icons for each column (i.e. Controls).
+     * @return string HTML
+     */
+    function get_righticonshtml() {
+        global $USER;
+
+        $iconshtml = '';
+        if ($USER->gradeediting[$this->courseid]) {
+
+            $iconshtml = '<tr class="controls_row">';
+
+            $columncount = 1;
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                // emulate grade element
+                $item =& $this->gtree->items[$itemid];
+                 
+                $eid = $this->gtree->get_item_eid($item);
+                $element = $this->gtree->locate_element($eid);
+            
+                $iconshtml .= '<th class="cell c'.$columncount++.' icons">' . $this->get_icons($element) . '</th>';
+            }
+            $iconshtml .= '</tr>';
+        }
+        return $iconshtml;
+    }
+
+   //Adding non sticky html 
+    /**
+     * Builds and returns the HTML code for the headers.
+     * @return string $headerhtml
+     */
+    function get_headerhtml() {
+        global $CFG, $USER;
+
+        $strsortasc   = $this->get_lang_string('sortasc', 'grades');
+        $strsortdesc  = $this->get_lang_string('sortdesc', 'grades');
+        $strfirstname = $this->get_lang_string('firstname');
+        $strlastname  = $this->get_lang_string('lastname');
+        $showuseridnumber = $this->get_pref('simple_showuseridnumber');
+
+        if ($this->sortitemid === 'lastname') {
+            if ($this->sortorder == 'ASC') {
+                $lastarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $lastarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $lastarrow = '';
+        }
+
+        if ($this->sortitemid === 'firstname') {
+            if ($this->sortorder == 'ASC') {
+                $firstarrow = print_arrow('up', $strsortasc, true);
+            } else {
+                $firstarrow = print_arrow('down', $strsortdesc, true);
+            }
+        } else {
+            $firstarrow = '';
+        }
+        // Prepare Table Headers
+        $headerhtml = '';
+
+        $numrows = count($this->gtree->levels);
+
+        $columns_to_unset = array();
+
+
+        foreach ($this->gtree->levels as $key=>$row) {
+            $columncount = 0;
+            if ($key == 0) {
+                // do not display course grade category
+                // continue;
+            }
+
+            $headerhtml .= '<tr class="heading r'.$this->rowcount++.'">';
+
+            if ($key == $numrows - 1) {
+                $headerhtml .= '<th class="fixedcolumn header c'.$columncount++.'" scope="col"><a href="'.$this->baseurl.'&amp;sortitemid=firstname">'
+                            . $strfirstname . '</a> '
+                            . $firstarrow. '/ <a href="'.$this->baseurl.'&amp;sortitemid=lastname">' . $strlastname . '</a>'. $lastarrow .'</th><th class="fixedcolumn header" c'.$columncount++.'" scope="col"></th>';
+                if ($showuseridnumber) {
+                    if ('idnumber' == $this->sortitemid) {
+                        if ($this->sortorder == 'ASC') {
+                            $idnumberarrow = print_arrow('up', $strsortasc, true);
+                        } else {
+                            $idnumberarrow = print_arrow('down', $strsortdesc, true);
+                        }
+                    } else {
+                        $idnumberarrow = '';
+                    }
+                    $headerhtml .= '<th class="fixedcolumn header c'.$columncount++.' useridnumber" scope="col"><a href="'.$this->baseurl.'&amp;sortitemid=idnumber">'
+                            . get_string('idnumber') . '</a> ' . $idnumberarrow . '</th>';
+                }
+             } else {
+                $colspan='colspan="2"';
+                if ($showuseridnumber) {
+                    $colspan = 'colspan="3" ';
+                }
+
+                $headerhtml .= '<td '.$colspan.'class=" fixedcolumn cell c'.$columncount++.' topleft">&nbsp;</td>';
+
+                if ($showuseridnumber) {
+                    $columncount++;
+                }
+            }
+
+            foreach ($row as $columnkey => $element) {
+                $sort_link = '';
+                if (isset($element['object']->id)) {
+                    $sort_link = $this->baseurl.'&amp;sortitemid=' . $element['object']->id;
+                }
+
+                $eid    = $element['eid'];
+                $object = $element['object'];
+                $type   = $element['type'];
+                $categorystate = @$element['categorystate'];
+                $itemmodule = null;
+                $iteminstance = null;
+
+                $columnclass = 'c' . $columncount++;
+                if (!empty($element['colspan'])) {
+                    $colspan = 'colspan="'.$element['colspan'].'"';
+                    $columnclass = '';
+                } else {
+                    $colspan = '';
+                }
+
+                if (!empty($element['depth'])) {
+                    $catlevel = ' catlevel'.$element['depth'];
+                } else {
+                    $catlevel = '';
+                }
+
+// Element is a filler
+                if ($type == 'filler' or $type == 'fillerfirst' or $type == 'fillerlast') {
+                    $headerhtml .= '<th class="'.$columnclass.' '.$type.$catlevel.'" '.$colspan.' scope="col">&nbsp;</th>';
+                }
+// Element is a category
+                else if ($type == 'category') {
+                    $parent_category = $object->get_parent_category();
+                    
+                    if ($parent_category) {
+                        $course_weight_total = $this->get_total_weights($parent_category);
+                    }
+                
+                    $headerhtml .= '<th class="header '. $columnclass.' category'.$catlevel.'" '.$colspan.' scope="col">'
+                                . shorten_text($element['object']->get_name());
+                    if ($object->grade_item->itemtype == 'category' 
+                        && $parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                        $weight = format_float($object->grade_item->aggregationcoef, 2); 
+                        $headerhtml .= ': '.$weight .' (<span class="gradeweight">' . 
+                            format_float(($weight/$course_weight_total) * 100, 2) . 
+                            '%</span>)' .' ';
+                    }
+                    $headerhtml .=  $this->get_collapsing_icon($element);
+
+                    // Print icons
+                    if ($USER->gradeediting[$this->courseid]) {
+                        $headerhtml .= $this->get_icons($element);
+                    }
+
+                    $headerhtml .= '</th>';
+                }
+
+// Element is a grade_item
+                else {
+                    $itemmodule = $element['object']->itemmodule;
+                    $iteminstance = $element['object']->iteminstance;
+
+                    if ($element['object']->id == $this->sortitemid) {
+                        if ($this->sortorder == 'ASC') {
+                            $arrow = $this->get_sort_arrow('up', $sort_link);
+                        } else {
+                            $arrow = $this->get_sort_arrow('down', $sort_link);
+                        }
+                    } else {
+                        $arrow = $this->get_sort_arrow('move', $sort_link);
+                    }
+
+                    $hidden = '';
+                    if ($element['object']->is_hidden()) {
+                        $hidden = ' hidden ';
+                    }
+        		    $headerhtml .= '<th class="header '.$columnclass.' '.$type.$catlevel.$hidden.'" scope="col" onclick="set_col(this.cellIndex)">';
+        		    if(!$object->is_course_item() && !$object->is_category_item()) {
+                        $endurl = '';
+                        if ($this->profileid && $anonymous = get_record('block_anon_grade_items', 'itemid', $object->id)) {
+                            $this->anonymous_items[$object->id] = $anonymous->completed;
+                        }
+
+                        if ($this->profileid && $anonymous && !$anonymous->completed){
+                            $endurl = '&amp;mode=anonymous&amp;fieldid='. $this->profileid . '">';
+                        }
+
+                        else {
+                            $endurl = '&amp;mode=grades&amp;group='.$this->currentgroup.'">';
+                        }
+                        $headerhtml .= '<a class="quickedit2" href="quick_edit.php?id='.$this->courseid.'&amp;itemid='.
+                            $element['object']->id. $endurl . get_string('quick_edit', 'gradereport_simple_grader').'</a>';
+                    }
+                    $headerlink = $this->gtree->get_element_header($element, true, $this->get_pref('simple_showactivityicons'), false);
+                    $headerhtml .= shorten_text($headerlink) . $arrow;
+                    $headerhtml .= '</th>';
+                }
+
+            }
+
+            $headerhtml .= '</tr>';
+        }
+        return $headerhtml;
+    }
+
+    /**
+     * Builds and return the HTML rows of the table (grades headed by student).
+     * @return string HTML
+     */
+    function get_studentshtml() {
+        global $CFG, $USER;
+
+        $studentshtml = '';
+        $strfeedback  = $this->get_lang_string("feedback");
+        $strgrade     = $this->get_lang_string('grade');
+        $gradetabindex = 1;
+        $showuserimage = $this->get_pref('simple_showuserimage');
+        $showuseridnumber = $this->get_pref('simple_showuseridnumber');
+        $numusers      = count($this->users);
+
+        // Preload scale objects for items with a scaleid
+        $scales_list = '';
+        $tabindices = array();
+
+        foreach ($this->gtree->items as $item) {
+            if (!empty($item->scaleid)) {
+                $scales_list .= "$item->scaleid,";
+            }
+
+            $tabindices[$item->id]['grade'] = $gradetabindex;
+            $tabindices[$item->id]['feedback'] = $gradetabindex + $numusers;
+            $gradetabindex += $numusers * 2;
+        }
+        $scales_array = array();
+
+        if (!empty($scales_list)) {
+            $scales_list = substr($scales_list, 0, -1);
+            $scales_array = get_records_list('scale', 'id', $scales_list);
+        }
+        
+        $row_classes = array(' even ', ' odd ');
+
+        $row_classes = array(' even ', ' odd ');
+
+        foreach ($this->users as $userid => $user) {
+
+            if ($this->canviewhidden) {
+                $altered = array();
+                $unknown = array();
+            } else {
+                $hiding_affected = grade_grade::get_hiding_affected($this->grades[$userid], $this->gtree->items);
+                $altered = $hiding_affected['altered'];
+                $unknown = $hiding_affected['unknown'];
+                unset($hiding_affected);
+            }
+
+            $columncount = 0;
+            // Student name and link
+            $user_pic = null;
+            if ($showuserimage) {
+                $user_pic = '<div class="userpic">'. custom_user_image($user) . '</div>';
+            } 
+
+            $studentshtml .= '<tr class="r'.$this->rowcount++ . $row_classes[$this->rowcount % 2] . '">'
+                          .'<th class="fixedcolumn header c'.$columncount++.' user" scope="row" onclick="set_row(this.parentNode.rowIndex);">'.$user_pic.'</a>
+				<a href="'.$CFG->wwwroot.'/course/user.php?id='.$this->course->id.'&amp;user='.$user->id.'&amp;mode=grade">'.fullname($user).'</a></th>
+                                <th class="fixedcolumn header c'.$columncount++.' user"><a href="quick_edit.php?id='.$this->courseid.
+                                '&amp;mode=user&amp;itemid='.$user->id.'">'.get_string('quick_edit', 'gradereport_simple_grader').'</a>';
+            $studentshtml .= "</th>";
+            
+            if ($showuseridnumber) {
+                $studentshtml .= '<th class="fixedcolumn header c'.$columncount++.' useridnumber" onclick="set_row(this.parentNode.rowIndex);">'.
+                        $user->idnumber.'</a></th>';
+            }
+
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+                $grade = $this->grades[$userid][$item->id];
+
+                // Get the decimal points preference for this item
+                $decimalpoints = $item->get_decimals();
+
+                if (in_array($itemid, $unknown)) {
+                    $gradeval = null;
+                } else if (array_key_exists($itemid, $altered)) {
+                    $gradeval = $altered[$itemid];
+                } else {
+                    $gradeval = $grade->finalgrade;
+                }
+
+                // MDL-11274
+                // Hide grades in the grader report if the current grader doesn't have 'moodle/grade:viewhidden'
+                if (!$this->canviewhidden and $grade->is_hidden()) {
+                    if (!empty($CFG->grade_hiddenasdate) and $grade->get_datesubmitted() and !$item->is_category_item() and !$item->is_course_item()) {
+                        // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
+                        $studentshtml .= '<td class="cell c'.$columncount++.'"><span class="datesubmitted">'.userdate($grade->get_datesubmitted(),get_string('strftimedatetimeshort')).'</span></td>';
+                    } else {
+                        $studentshtml .= '<td class="cell c'.$columncount++.'">-</td>';
+                    }
+                    continue;
+                }
+
+                // emulate grade element
+                $eid = $this->gtree->get_grade_eid($grade);
+                $element = array('eid'=>$eid, 'object'=>$grade, 'type'=>'grade');
+                $anonymous_item = array_key_exists($item->id, $this->anonymous_items);
+
+                $cellclasses = 'cell c'.$columncount++;
+                if ($item->is_category_item()) {
+                    $cellclasses .= ' cat';
+                }
+                if ($item->is_course_item()) {
+                    $cellclasses .= ' course';
+                }
+                if ($grade->is_overridden()) {
+                    $cellclasses .= ' overridden';
+                }
+
+                if ($grade->is_excluded()) {
+                    $cellclasses .= ' excluded';
+                }
+
+                $studentshtml .= '<td class="'.$cellclasses.'">';
+
+                if ($grade->is_excluded()) {
+                    $studentshtml .= '<span class="excludedfloater">' . get_string('excluded', 'grades') . '</span>' . ' ';
+                }
+
+                // Do not show any icons if no grade (no record in DB to match)
+//-------------------------- Changed that ion print out for course categories --------------------------//
+                if (!$item->needsupdate and $USER->gradeediting[$this->courseid] and !$item->is_category_item() 
+                    and !$item->is_course_item() and !$anonymous_item){
+                    $studentshtml .= $this->get_icons($element);
+                }
+
+                $hidden = '';
+                if ($grade->is_hidden()) {
+                    $hidden = ' hidden ';
+                }
+
+                $gradepass = ' gradefail '; 
+                if ($grade->is_passed($item)) {
+                    $gradepass = ' gradepass ';
+                } elseif (is_null($grade->is_passed($item))) {
+                    $gradepass = '';
+                }
+
+                // if in editting mode, we need to print either a text box
+                // or a drop down (for scales)
+                // grades in item of type grade category or course are not directly editable
+                if ($item->needsupdate) {
+                    $studentshtml .= '<span class="gradingerror'.$hidden.'">'.get_string('error').'</span>';
+
+                } else if ($USER->gradeediting[$this->courseid]) {
+                    // Changed for multiplicator
+                    $gradeval = ($item->itemtype == 'manual') ? $grade->rawgrade : $grade->finalgrade;
+                    // End change
+
+                    if ($item->scaleid && !empty($scales_array[$item->scaleid])) {
+                        $scale = $scales_array[$item->scaleid];
+                        $gradeval = (int)$gradeval; // scales use only integers
+                        $scales = explode(",", $scale->scale);
+                        // reindex because scale is off 1
+
+                        // MDL-12104 some previous scales might have taken up part of the array
+                        // so this needs to be reset
+                        $scaleopt = array();
+                        $i = 0;
+                        foreach ($scales as $scaleoption) {
+                            $i++;
+                            $scaleopt[$i] = $scaleoption;
+                        }
+
+                        // Removed because it was confusing to teachers
+                        if (/*$this->get_pref('simple_quickgrading') and*/ $grade->is_editable() && !$item->is_course_item() ) {
+                            $oldval = empty($gradeval) ? -1 : $gradeval;
+                            if (empty($item->outcomeid)) {
+                                $nogradestr = $this->get_lang_string('nograde');
+                            } else {
+                                $nogradestr = $this->get_lang_string('nooutcome', 'grades');
+                            }
+                            $studentshtml .= '<input id="oldgrade_'.$userid.'_'.$item->id.'" type="hidden" name="oldgrade_'.$userid.'_'
+                                          .$item->id.'" value="'.$oldval.'"/>';
+                            $studentshtml .= choose_from_menu($scaleopt, 'grade_'.$userid.'_'.$item->id,
+                                                              $gradeval, $nogradestr, '', '-1',
+                                                              true, false, $tabindices[$item->id]['grade']);
+                        } elseif(!empty($scale)) {
+                            $scales = explode(",", $scale->scale);
+
+                            // invalid grade if gradeval < 1
+                            if ($gradeval < 1) {
+                                $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">-</span>';
+                            } else {
+                                $gradeval = (int)bounded_number($grade->grade_item->grademin, $gradeval, $grade->grade_item->grademax); //just in case somebody changes scale
+                                $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.$scales[$gradeval-1].'</span>';
+                            }
+                        } else {
+                            // no such scale, throw error?
+                        }
+
+                    } else if ($item->gradetype != GRADE_TYPE_TEXT) { // Value type
+//-------------------------- Changed: we just print out categories -------------------------------//
+                        if ($item->is_course_item() or $item->is_category_item() or $anonymous_item) {
+                            $gradedisplaytype = $item->get_displaytype();
+                            $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null).'</span>';  
+                        } else if (!empty($this->anonymous_items[$item->id])) {
+                            $studentshtml .= '<span class="gradevalue'. $hidden. '">-</span>';
+                        }
+                        // Removed because teachers found this to be confusing 
+                        else if (/*$this->get_pref('quickgrading') and*/ $grade->is_editable()) {
+                            $value = format_float($gradeval, $decimalpoints);
+                            $studentshtml .= '<input id="oldgrade_'.$userid.'_'.$item->id.'" type="hidden" name="oldgrade_'.$userid.'_'.$item->id.'" value="'.$value.'" />';
+                            $studentshtml .= '<input id="grade_'.$userid.'_'.$item->id.'" size="6" tabindex="' . $tabindices[$item->id]['grade']
+                                          . '" type="text" title="'. $strgrade .'" name="grade_'
+                                          .$userid.'_' .$item->id.'" value="'.$value.'" />';
+                        } else {
+                            $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'.format_float($gradeval, $decimalpoints).'</span>';
+                        }
+                    }
+
+
+                    // If quickfeedback is on, print an input element
+                    if ($this->get_pref('simple_showquickfeedback') and $grade->is_editable() and $item->itemtype != 'anonymous') {
+                        // Removed because it was confusing to teachers
+                        /*if ($this->get_pref('simple_quickgrading')) {
+                            $studentshtml .= '<br />';
+                        }*/
+                        $studentshtml .= '<input id="oldfeedback_'.$userid.'_'.$item->id.'" type="hidden" name="oldfeedback_'
+                                      .$userid.'_'.$item->id.'" value="' . s($grade->feedback) . '" />';
+                        $studentshtml .= '<input id="feedback_'.$userid.'_'.$item->id.'" class="quickfeedback" tabindex="' . $tabindices[$item->id]['feedback']
+                                      . '" size="6" title="' . $strfeedback . '" type="text" name="feedback_'
+                                      .$userid.'_'.$item->id.'" value="' . s($grade->feedback) . '" />';
+                    }
+
+                } else { // Not editing
+                    $gradedisplaytype = $item->get_displaytype();
+
+                    // If feedback present, surround grade with feedback tooltip: Open span here
+                    if (!empty($grade->feedback)) {
+                        $overlib = '';
+                        $feedback = addslashes_js(trim(format_string($grade->feedback, $grade->feedbackformat)));
+                        $overlib = "return overlib('$feedback', BORDER, 0, FGCLASS, 'feedback', "
+                                  ."CAPTIONFONTCLASS, 'caption', CAPTION, '$strfeedback');";
+                        $studentshtml .= '<span onmouseover="'.s($overlib).'" onmouseout="return nd();">';
+                    }
+
+                    $gradedisplay = ($item->itemtype == 'anonymous') ? '-' : grade_format_gradevalue($gradeval, $item, true, $gradedisplaytype, null);
+
+                    if ($item->needsupdate) {
+                        $studentshtml .= '<span class="gradingerror'.$hidden.$gradepass.'">'.get_string('error').'</span>';
+                    } else {
+                        $studentshtml .= '<span class="gradevalue'.$hidden.$gradepass.'">'. $gradedisplay .'</span>';
+                    }
+
+                    // Close feedback span
+                    if (!empty($grade->feedback)) {
+                        $studentshtml .= '</span>';
+                    }
+                }
+
+                if (!empty($this->gradeserror[$item->id][$userid])) {
+                    $studentshtml .= $this->gradeserror[$item->id][$userid];
+                }
+
+                $studentshtml .=  '</td>' . "\n";
+            }
+            $studentshtml .= '</tr>';
+        }
+        return $studentshtml;
+    }
+    
+    /**
+     * Builds and return the HTML row of column totals.
+     * @param  bool $grouponly Whether to return only group averages or all averages.
+     * @return string HTML
+     */
+    function get_avghtml($grouponly=false) {
+        global $CFG, $USER;
+
+        if (!$this->canviewhidden) {
+            // totals might be affected by hiding, if user can not see hidden grades the aggregations might be altered
+            // better not show them at all if user can not see all hideen grades
+            return;
+        }
+
+        $averagesdisplaytype   = $this->get_pref('simple_averagesdisplaytype');
+        $averagesdecimalpoints = $this->get_pref('simple_averagesdecimalpoints');
+        $meanselection         = $this->get_pref('simple_meanselection');
+        $shownumberofgrades    = $this->get_pref('simple_shownumberofgrades');
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $avghtml = '';
+        $avgcssclass = 'avg';
+
+        if ($grouponly) {
+            $straverage = get_string('groupavg', 'grades');
+            $showaverages = $this->currentgroup;
+            $groupsql = $this->groupsql;
+            $groupwheresql = $this->groupwheresql;
+            $avgcssclass = 'groupavg';
+        } else {
+            $straverage = get_string('overallaverage', 'grades');
+            $showaverages = $this->get_pref('simple_showaverages');
+            $groupsql = "";
+            $groupwheresql = "";
+        }
+
+        if ($shownumberofgrades) {
+            $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
+        }
+
+        $totalcount = $this->get_numusers($grouponly);
+
+        if ($showaverages) {
+
+            // find sums of all grade items in course
+            $SQL = "SELECT DISTINCT (
+                    g.itemid
+                    ), SUM( g.finalgrade ) AS sum
+                    FROM {$CFG->prefix}grade_items gi
+                    JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
+                    JOIN {$CFG->prefix}user u ON g.userid = u.id
+                    JOIN (
+                    SELECT DISTINCT (ra.userid)
+                    FROM {$CFG->prefix}role_assignments ra
+                    WHERE ra.roleid IN ($this->gradebookroles)
+                        AND ra.contextid ".get_related_contexts_string($this->context)."
+                    ) AS sub ON sub.userid = u.id
+                    $groupsql
+                    WHERE gi.courseid= $this->courseid
+                    AND g.finalgrade IS NOT NULL
+                    $groupwheresql
+                    GROUP BY g.itemid";
+
+            /*$SQL = "SELECT g.itemid, SUM(g.finalgrade) AS sum
+                      FROM {$CFG->prefix}grade_items gi
+                           JOIN {$CFG->prefix}grade_grades g      ON g.itemid = gi.id 
+                           JOIN {$CFG->prefix}user u              ON u.id = g.userid 
+                           $groupsql
+                     WHERE gi.courseid = $this->courseid
+                           AND g.finalgrade IS NOT NULL
+                           $groupwheresql
+                  GROUP BY g.itemid";*/
+            $sum_array = array();
+            if ($sums = get_records_sql($SQL)) {
+                foreach ($sums as $itemid => $csum) {
+                    $sum_array[$itemid] = $csum->sum;
+                }
+            }
+
+            $columncount=0;
+            $colspan='colspan="2"';
+            if ($showuseridnumber) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $avghtml = '<tr class="' . $avgcssclass . ' r'.$this->rowcount++.'"><th class="fixedcolumn header c0" '.$colspan.'scope="row">'.$straverage.'</th>';
+
+            if ($showuseridnumber) {
+                $columncount++;
+            }
+
+            // MDL-10875 Empty grades must be evaluated as grademin, NOT always 0
+            // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
+            /*$SQL = "SELECT gi.id, COUNT(u.id) AS count
+                      FROM {$CFG->prefix}grade_items gi
+                           CROSS JOIN {$CFG->prefix}user u
+                           JOIN {$CFG->prefix}role_assignments ra        ON ra.userid = u.id
+                           LEFT OUTER JOIN  {$CFG->prefix}grade_grades g ON (g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL) 
+                           $groupsql
+                     WHERE gi.courseid = $this->courseid
+                           AND ra.roleid in ($this->gradebookroles)
+                           AND ra.contextid ".get_related_contexts_string($this->context)."
+                           AND g.id IS NULL
+                           $groupwheresql
+                  GROUP BY gi.id";*/
+
+            /*
+                Changed the query to support people in multiple roles; By doing it this way, we get the 
+                total number of graded items, instead of ungraded items
+             */ 
+            $SQL = "SELECT DISTINCT (gi.id), COUNT(u.id) AS count
+                        FROM {$CFG->prefix}grade_items gi
+                        JOIN {$CFG->prefix}grade_grades g ON g.itemid = gi.id
+                        JOIN {$CFG->prefix}user u ON u.id = g.userid
+                        JOIN (SELECT DISTINCT (ra.userid)
+                                FROM {$CFG->prefix}role_assignments ra
+                                WHERE ra.roleid IN ($this->gradebookroles)
+                                  AND ra.contextid ".get_related_contexts_string($this->context)."
+                             ) AS sub ON sub.userid = u.id
+                        $groupsql
+                        WHERE gi.courseid = $this->courseid
+                        AND g.finalgrade IS NOT NULL
+                        $groupwheresql
+                        GROUP BY g.itemid";
+ 
+            $ungraded_counts = get_records_sql($SQL);
+
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+
+                if ($item->needsupdate) {
+                    $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
+                    continue;
+                }
+
+                if (!isset($sum_array[$item->id])) {
+                    $sum_array[$item->id] = 0;
+                }
+
+                if (empty($ungraded_counts[$itemid])) {
+                    $ungraded_count = 0;
+                } else {
+                    $ungraded_count = $ungraded_counts[$itemid]->count;
+                }
+
+                if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
+                    $mean_count = /*$totalcount - */$ungraded_count;
+                } else { // Bump up the sum by the number of ungraded items * grademin
+                    $sum_array[$item->id] += $ungraded_count * $item->grademin;
+                    $mean_count = $totalcount;
+                }
+
+                $decimalpoints = $item->get_decimals();
+
+                // Determine which display type to use for this average
+                if ($USER->gradeediting[$this->courseid]) {
+                    $displaytype = GRADE_DISPLAY_TYPE_REAL;
+
+                } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
+                    $displaytype = $item->get_displaytype();
+
+                } else {
+                    $displaytype = $averagesdisplaytype;
+                }
+
+                // Override grade_item setting if a display preference (not inherit) was set for the averages
+                if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
+                    $decimalpoints = $item->get_decimals();
+
+                } else {
+                    $decimalpoints = $averagesdecimalpoints;
+                }
+
+                if (!isset($sum_array[$item->id]) || $mean_count == 0) {
+                    $avghtml .= '<td class="cell c' . $columncount++.'">-</td>';
+                } else {
+                    $sum = $sum_array[$item->id];
+                    $avgradeval = $sum/$mean_count;
+                    $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
+
+                    $numberofgrades = '';
+                    if ($shownumberofgrades) {
+                        $numberofgrades = " ($mean_count)";
+                    }
+
+                    $avghtml .= '<td class="cell c' . $columncount++.'">'.$gradehtml.$numberofgrades.'</td>';
+                }
+            }
+            $avghtml .= '</tr>';
+        }
+        return $avghtml;
+    }
+
+    /**
+     * Builds and return the HTML row of ranges for each column (i.e. range).
+     * @return string HTML
+     */
+    function get_rangehtml() {
+        global $USER;
+        $showuseridnumber      = $this->get_pref('simple_showuseridnumber');
+
+        $scalehtml = '';
+        if ($this->get_pref('simple_showranges')) {
+            $rangesdisplaytype   = $this->get_pref('simple_rangesdisplaytype');
+            $rangesdecimalpoints = $this->get_pref('simple_rangesdecimalpoints');
+
+            $columncount=0;
+            $colspan='colspan="2"';
+            if ($showuseridnumber) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $scalehtml = '<tr class="r'.$this->rowcount++.'">'
+                       . '<th class="fixedcolumn header c0 range" '.$colspan.'scope="row">'.$this->get_lang_string('range','grades').'</th>';
+
+            if ($showuseridnumber) {
+                $columncount++;
+            }
+
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                $item =& $this->gtree->items[$itemid];
+
+                // Determine which display type to use for this average
+                if ($USER->gradeediting[$this->courseid]) {
+                    $displaytype = GRADE_DISPLAY_TYPE_REAL;
+
+                } else if ($rangesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave report and user prefs
+                    $displaytype = $item->get_displaytype();
+
+                } else {
+                    $displaytype = $rangesdisplaytype;
+                }
+
+                // Override grade_item setting if a display preference (not default) was set for the averages
+                if ($rangesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
+                    $decimalpoints = $item->get_decimals();
+
+                } else {
+                    $decimalpoints = $rangesdecimalpoints;
+                }
+
+                if ($displaytype == GRADE_DISPLAY_TYPE_PERCENTAGE) {
+                    $grademin = "0 %";
+                    $grademax = "100 %";
+
+                } else {
+                    $grademin = grade_format_gradevalue($item->grademin, $item, true, $displaytype, $decimalpoints);
+                    $grademax = grade_format_gradevalue($item->grademax, $item, true, $displaytype, $decimalpoints);
+                }
+
+                $hidden = '';
+                if ($item->is_hidden()) {
+                    $hidden = ' hidden ';
+                }
+
+                $scalehtml .= '<th class="header c'.$columncount++.' range"><span class="rangevalues'.$hidden.'">'. $grademin.'&ndash;'. $grademax.'</span></th>';
+            }
+            $scalehtml .= '</tr>';
+        }
+        return $scalehtml;
+    }
+    
+    /**
+     * Builds and return the HTML row of ranges for each column (i.e. range).
+     * @return string HTML
+     */
+    function get_iconshtml() {
+        global $USER;
+
+        $iconshtml = '';
+        if ($USER->gradeediting[$this->courseid]) {
+
+            $colspan='colspan="2"';
+            if ($this->get_pref('simple_showuseridnumber')) {
+                $colspan = 'colspan="3" ';
+            }
+
+            $iconshtml = '<tr class="r'.$this->rowcount++.'">'
+                       . '<th class="header c0 range" scope="row" '.$colspan.'>'.$this->get_lang_string('controls','grades').'</th>';
+
+            $columncount = 1;
+            foreach ($this->gtree->items as $itemid=>$unused) {
+                // emulate grade element
+                $item =& $this->gtree->items[$itemid];
+                 
+                $eid = $this->gtree->get_item_eid($item);
+                $element = $this->gtree->locate_element($eid);
+            
+                $iconshtml .= '<th class="cell c'.$columncount++.' icons">' . $this->get_icons($element) . '</th>';
+            }
+            $iconshtml .= '</tr>';
+        }
+        return $iconshtml;
+    }
+
+    function get_total_weights($parent_category) {
+        $grade_items = $parent_category->get_children();
+
+        $total_weight = 0;
+        foreach ($grade_items as $gid=>$grade_item) {
+            if ($grade_item['type'] == 'category') {
+                $item = $grade_item['object']->get_grade_item();
+            } else {
+                $item = $grade_item['object'];
+            }
+            $total_weight += (float)$item->aggregationcoef;
+        }
+        return $total_weight;
+    }
+
+}
+?>
+
Index: grade/report/simple_grader/README.txt
===================================================================
RCS file: grade/report/simple_grader/README.txt
diff -N grade/report/simple_grader/README.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/README.txt	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,48 @@
+Simple Grader Post-installation Notes
+=====================================
+
+Change the default aggregation coefficient of grade items
+---------------------------------------------------------
+Open {MOODLE_BASE}/lib/grade/grade_item.php and seek to line 197.
+Make the following change:
+
+var $aggregationcoef = 0; => var $aggregationcoef = 1;
+
+Note: The line number may not be exact in your version, but it should be close.
+
+
+Add a check for the Simple Grader Report Plugin to gradelib
+-----------------------------------------------------------
+Add the the following lines to the beginning of the function 
+grade_regrade_final_grade in {MOODLE_BASE}/lib/gradelib.php:
+
+// Check for Simple Grader Report
+global $CFG;
+     
+$exists = file_exists($CFG->dirroot. '/grade/report/simple_grader/lib/simple_gradelib.php');
+if ($exists) {
+     require_once($CFG->dirroot . '/grade/report/simple_grader/lib/simple_gradelib.php');
+     return simple_grade_regrade_final_grades($courseid, $userid, $updated_item);
+}   
+// End check for Simple Grader Report
+
+If Simple Grader Report exists, its regrade function is called instead of the default being run.
+This is necessary because Simple Grader Report does not uses the same grading 
+rules and algorithms as the default grader report.
+
+Check for simple_grader in report index.php
+----------------------------------------------------------
+Change the following lines from:
+
+ if (empty($last)) {
+     if (in_array('grader', $reports)) {
+         $last = 'grader';
+     }
+
+to:
+
+ if (empty($last)) {
+     if (in_array('simple_grader', $reports)) {
+         $last = 'simple_grader';
+     }
+
Index: grade/report/projected/rpc.php
===================================================================
RCS file: grade/report/projected/rpc.php
diff -N grade/report/projected/rpc.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/rpc.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,497 @@
+<?php
+
+/*
+ * @author Adam Zapletal
+ * February 27, 2008
+ */
+
+  ////////////////
+ //  REQUIRES  //
+////////////////
+
+require_once('../../../config.php');
+require_once($CFG->libdir . '/mathslib.php');
+require_once($CFG->libdir . '/gradelib.php');
+require_once($CFG->libdir . '/moodlelib.php');
+require_once($CFG->libdir . '/grade/constants.php');
+require_once($CFG->libdir . '/grade/grade_item.php');
+require_once($CFG->libdir . '/grade/grade_grade.php');
+require_once($CFG->libdir . '/grade/grade_category.php');
+
+  //////////////////////////
+ //  INTERNAL FUNCTIONS  //
+//////////////////////////
+
+// Takes an array of id=value pairs and splits and organizes them
+// into an array of itemid => rounded_value pairs
+// Particularly, $inputs will be the ids and values of the dynamically 
+// generated textboxes from the index page passed in through the ajax call
+function read_new_grades($inputs) {
+    foreach ($inputs as $input) {
+        // Skip processing input item unless it has an element id and
+        // a numeric value
+        list($elementid, $value) = explode('=', $input);
+
+        if (!($elementid && (is_numeric($value)) || $value == 'switch_me')) {
+            continue;
+        }
+
+        // Skip processing input item if element is not a grade element
+        list($trash, $name, $id) = explode('_', $elementid);
+
+        if ($name != 'grade') {
+            continue;
+        }
+
+        $new_grades[$id] = round($value, 5);
+    }
+
+   return $new_grades;
+}
+
+// Filter function for array_filter
+// Checks if a category or item has a calculation
+function has_calculation($obj) {
+    return (bool)$obj->calculation;
+}   
+
+// Filter function for array_filter
+// Expects an item, returns only category totals
+function is_category_total($obj) {
+    return $obj->itemtype == 'category';
+}
+
+// Filter function for array_filter
+// Expects an item, returns only manual items
+function is_manual($obj) {
+    return $obj->itemtype == 'manual';
+}
+
+// If a course has multiple calculated items, one may depend on the
+// calculation of another. Therefore, we have to decide which calculation(s)
+// to run first so the later ones can be accurate.
+// Expects the course's items array, and an array of ordered item ids. The
+// second array will be built by this function's recursive calls to itself.
+function build_dependency_order($items, $ordered=null) {
+    if (!$ordered) {
+        $ordered = array();
+    }
+
+    $calc_items = array_filter($items, 'has_calculation');
+
+    foreach ($calc_items as $id => $item) {
+        preg_match_all('/##gi(\d+)##/', $item->calculation, $matches);
+        $depends_on = array_unique($matches[1]);
+
+        $inner_array = array();
+
+        foreach ($depends_on as $gi_id) {
+            $inner_array[$gi_id] = $items[$gi_id];
+        }
+
+        $ordered = build_dependency_order($inner_array, $ordered);
+
+        $ordered[] = $id;
+
+        foreach ($depends_on as $gi_id) {
+            if ($items[$gi_id]->calculation) {
+                $ordered[] = $gi_id;
+            }
+        }
+    }
+
+    return $ordered;
+}
+
+// Recursively checks that each prerequisite for this item's calculation
+// has already been calculated
+function prepare_for_calculation($itemid, $items) {
+    $params = array();
+    preg_match_all('/##(gi\d+)##/', $items[$itemid]->calculation, $matches);
+    $depends_on = array_unique($matches[1]);
+
+    foreach ($depends_on as $gi_id) {
+        $itemid = substr($gi_id, 2);
+
+        if ($items[$itemid]->calculation && !$items[$itemid]->calculated) {
+            $tmp_params = prepare_for_calculation($itemid, $items);
+            $items[$itemid]->value = use_formula($items[$itemid]->calculation,
+                $tmp_param);
+
+        } else {
+            $params[$gi_id] = $items[$itemid]->value;
+        }
+    }
+
+    return $params;
+}
+
+// Takes the category id of the category that needs to be aggregated, the
+// course's categories array, the courses items array, and a flag indicating
+// whether or not this is the course total category.
+// Returns an array of the two arrays that are prepared to be passed to 
+// aggregate_category.
+function prepare_for_aggregation($catid, $categories, $items, $course_total) {
+    $required_items = array();
+    $cat_items = array();
+    $grade_values = array();
+
+    if ($categories[$catid]->aggregatesubcats) {
+        // If we are aggregating subcategories, we need all grade items from this
+        // category down.
+        $manual_items = array_filter($items, 'is_manual');
+
+        foreach ($manual_items as $id => $item) {
+            if (!(strpos($categories[$item->categoryid]->path, $categories[$catid]->path) === false)) {
+                $required_items[] = $id;
+            }
+        }
+    } else {
+        // If we are not aggregating subcategories, we only need this category's
+        // immediate items and the category totals inside it.
+        foreach ($items as $id => $item) {
+            if (($item->categoryid == $catid && $item->itemtype != 'category') || 
+                ($course_total && $item->parent == $catid)) {
+                // An immediate item has been found.
+                $required_items[] = $id;
+            } else if (!(strpos($categories[$item->categoryid]->path, $categories[$catid]->path) === false)) {
+                if ($item->itemtype == 'category' && $item->categoryid != $catid) {
+                    // A nested category total has been found.
+                    $required_items[] = $id;
+                }
+            }
+        }
+    }
+ 
+    // Prepare the grade_values and cat_items arrays from required_items
+    if ($categories[$catid]->aggregation == GRADE_AGGREGATE_SUM) {
+        foreach ($required_items as $id) {
+            $grade_values[$id] = $items[$id]->value;
+            $cat_items[$id] = $items[$id];
+        }
+    } else {
+        foreach ($required_items as $id) {
+            $grade_values[$id] = grade_grade::standardise_score($items[$id]->value,
+                $items[$id]->grademin, $items[$id]->grademax, 0, 1);
+            $cat_items[$id] = $items[$id];
+        }
+    }
+
+    return array($grade_values, $cat_items);
+}
+
+// Calculates a grade using a formula with a given calculation
+// This is a hacked-together verison of grade_item->use_formula
+function use_formula($calculation, $params) {
+    $formula = new calc_formula(preg_replace('/##(gi\d+)##/', '\1', $calculation));
+    $formula->set_params($params);
+
+    return $formula->evaluate();
+}
+
+// Builds the paramaters array that will be passed to use_formula when
+// calculating an item. This is abstracted out of compute_items because it has
+// to be called explicitly when computing the course total
+function build_params($items, $calculation) {
+    $params = array();
+    preg_match_all('/##(gi\d+)##/', $calculation, $matches);
+
+    foreach(array_unique($matches[1]) as $gi_id) {
+        $params[$gi_id] = $items[substr($gi_id, 2)]->value;
+    }
+
+    return $params;
+}
+
+
+// Calculates each item, if necessary, and returns the items array with updated
+// values for those that were calculated.
+function compute_items($items, $calc_order) {
+    foreach ($calc_order as $id) {
+        $params = build_params($items, $items[$id]->calculation);
+        $items[$id]->value = use_formula($items[$id]->calculation, $params);
+        $items[$id]->calculated = true;
+    }
+
+    return $items;
+}
+
+// Takes the course's array of categories and returns an array of category ids
+// that are in the order in which their respective categories should be 
+// aggregated. A category may depend on the aggregation/category total of 
+// another, so this must be done.
+function order_categories($categories) {
+    $order = array();
+
+    ksort($categories);
+
+    foreach ($categories as $id => $category) {
+        foreach (explode('/', $category->path) as $id) {
+            if (!in_array($id, $order) && array_key_exists($id, $categories)) {
+                $order[] = $id;
+            }
+        }
+    }
+
+    return array_reverse(array_filter($order));
+}
+
+// When aggregating categories, we do not have access to the id of item which
+// represents each category's total, given our data structure. This function
+// builds a lookup associating each category_id to the id of the corresponding
+// category total item.
+function build_category_lookup($items) {
+    $lookup = array();
+
+    // Get an array of all category total items
+    $cat_totals = array_filter($items, 'is_category_total');
+
+    foreach ($cat_totals as $itemid => $itemdata) {
+        $lookup[$itemdata->categoryid] = $itemid;
+    }
+
+    return $lookup;
+}
+
+// Abstracts the aggregation of a single category. Takes the course's items and
+// categories array, the id of the category that needs to be aggregated, and a
+// flag that indicates whether or not the course total is being passed it.
+// The course total is a special case because the items on which it depends
+// have a NULL categoryid.
+function aggregate_category($items, $catid, $categories, $course_total=false) {
+    $agg_data = prepare_for_aggregation($catid, $categories, $items, $course_total);
+    $grade_values = $agg_data[0];
+    $cat_items = $agg_data[1];
+
+    $cat_obj = new grade_category(array('aggregation' => $categories[$catid]->aggregation,
+       'droplow' => $categories[$catid]->droplow, 'keephigh' => $categories[$catid]->keephigh), false);
+
+    // Apply limit rules (droplow, keephigh) and sort
+    $cat_obj->apply_limit_rules($grade_values);
+    asort($grade_values, SORT_NUMERIC);
+
+    // Do the math and return the value
+
+    // NEW 07/16/08
+    // Anonymous block must be checked, and extra credit must be added.
+    // This also happens for the course total.
+    global $anon_block_exists;
+
+    $extra_credit = 0;
+
+    // NEW 07/30/08
+    // Simple Grader Report must be checked for proper summing.
+    // This also happens for the course total.
+    global $simple_grader_exists;
+
+    if ($cat_obj->aggregation == GRADE_AGGREGATE_SUM) {
+        if ($simple_grader_exists) {
+            $agg_grade = simple_category_get_sum($cat_obj, $cat_items, $grade_values);
+        } else {
+            $agg_grade = projected_sum_grades($catid, $cat_obj, $grade_values, $cat_items);
+        }
+    } else {
+        if ($anon_block_exists) {
+            $extra_credit = get_category_extra_credit_score($grade_values, $cat_items);
+        }
+
+        if ($simple_grader_exists && $cat_obj->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) {
+            $agg_grade = simple_aggregate_values($grade_values, $cat_items);
+        } else {
+            $agg_grade = $cat_obj->aggregate_values($grade_values, $cat_items);
+        }
+    }
+
+    return array($agg_grade, $extra_credit);
+}
+
+// Takes the course's items array and the course's categories array.
+// Calls aggregate_category on each category and fills the items array
+// with the computed values. Then, it returns the array.
+function compute_categories($items, $categories) {
+    $lookup = build_category_lookup($items);
+    $order = order_categories($categories);
+
+    foreach ($order as $catid) {
+        $agg_return = aggregate_category($items, $catid, $categories); 
+        $agg_grade = $agg_return[0];
+        $extra_credit = $agg_return[1];
+
+        if ($categories[$catid]->aggregation == GRADE_AGGREGATE_SUM) {
+            $finalgrade = $agg_grade;
+        } else {
+            $finalgrade = grade_grade::standardise_score($agg_grade,
+                0, 1, $items[$lookup[$catid]]->grademin, $items[$lookup[$catid]]->grademax);
+        }
+
+        $items[$lookup[$catid]]->value = $finalgrade + $extra_credit;
+        $items[$lookup[$catid]]->aggregated = true;
+    }
+
+    return $items;
+}
+
+// NEW 07/29/08
+// All checks for GRADE_AGGREGATE_SUM are new as well
+// This function is a tweaked copy of grade_category's sum_graded method. It 
+// must be pulled out and tweaked so we don't save anything to the database.
+function projected_sum_grades($catid, $cat_obj, $grade_values, $items) {
+    // ungraded and exluded items are not used in aggregation
+    foreach ($grade_values as $itemid=>$v) {
+        if (is_null($v)) {
+            unset($grade_values[$itemid]);
+        }
+        /* else if (in_array($itemid, $excluded)) {
+            unset($grade_values[$itemid]);
+        }
+        */
+    }
+
+    // use 0 if grade missing, droplow used and aggregating all items
+    if (!$cat_obj->aggregateonlygraded and !empty($cat_obj->droplow)) {
+        foreach($items as $itemid=>$value) {
+            // if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) {
+            if (!isset($grade_values[$itemid])) {
+                $grade_values[$itemid] = 0;
+            }
+        }
+    }
+
+    $max = 0;
+
+    //find max grade
+    foreach ($items as $item) {
+        if ($item->aggregationcoef > 0) {
+            // extra credit from this activity - does not affect total
+            continue;
+        }
+
+        if ($item->gradetype == GRADE_TYPE_VALUE) {
+            $max += $item->grademax;
+        } else if ($item->gradetype == GRADE_TYPE_SCALE) {
+            $max += $item->grademax - 1; // scales min is 1
+        }
+    }
+
+    $cat_obj->apply_limit_rules($grade_values);
+
+    $sum = array_sum($grade_values);
+
+    $finalgrade = bounded_number(0, $sum, $max);
+
+    return $finalgrade;
+
+}
+
+// Writes a response string to be handled by javascript when the request
+// returns. Gleans data from the $items array for the textboxes whose values 
+// need to be updated on the page.
+function prepare_response_string($items) {
+    $out = '';
+    foreach ($items as $id => $item) {
+        if ($item->calculated || $item->aggregated) {
+            if (!$out == '') {
+                $out .= '|';
+            }
+
+            // NEW 03/11/08
+            // Fix for percentage display bug
+            $formatted = grade_format_gradevalue(number_format($item->value, 2), $item, true, $item->display, $item->decimals);
+            $out .= 'calc_item_grade_' . $id . '=<b>' . $formatted . '</b>'; 
+        }
+    }
+
+    return $out;
+}
+
+  ////////////
+ //  MAIN  //
+////////////
+
+// User must be logged in
+// We don't want arbitrary requests being made to this page
+require_login();
+
+// NEW 07/16/08
+// First we must check for an installation of the anonymous grade block.
+// If it exists, we have to call it's aggregation instead of the normal one.
+if (get_field('block', 'id', 'name', 'anonymous_grade')) {
+    require_once($CFG->dirroot . '/blocks/anonymous_grade/lib.php');
+    $anon_block_exists = True;
+} else {
+    $anon_block_exists = False;
+}
+
+// NEW 07/30/08
+// We also need to check for an installation of the simple grader report so 
+// we can use its sum function rather than the regular one if needed.
+if (in_array('simple_grader', get_list_of_plugins('grade/report', 'CVS'))) {
+    require_once($CFG->dirroot . '/grade/report/simple_grader/lib/simple_grade_hook.php');
+    $simple_grader_exists = True;
+} else {
+    $simple_grader_exists = False;
+}
+
+// Read the post data and mold it into something useful
+$inputs = explode('|', required_param('inputdata', PARAM_RAW));
+
+// Rebuild the course information data structure then split it into meaningful parts
+$course_data = $SESSION->projected_ajax_data;
+$items = $course_data['items'];
+$categories = $course_data['categories'];
+$course_total = $course_data['course_total'];
+unset($course_data);
+
+// Add the new grades from textboxes to the items array
+$new_grades = read_new_grades($inputs);
+foreach ($new_grades as $id => $value) {
+    // If value is 'switch_me', then we need to input the grade item's minimum value
+    // This could not be done earlier because we did not have that data.
+    if ($value == 'switch_me') {
+        $value = $items[$id]->grademin;
+    }
+
+    $items[$id]->value = number_format($value, 5);
+}
+
+// Calculate all items with a calculation by passing the course's items array
+// and a unique, ordered array of item_ids to compute_items
+$items = compute_items($items, array_unique(build_dependency_order($items)));
+
+// Update the items array with computed category values.
+// A category can have a calculated total, so at this point it would already
+// be calculated. Therefore, the second argument must be the $categories array 
+// with any calculated totals filtered out. 
+$items = compute_categories($items, array_diff_key($categories, 
+    array_filter($categories, 'has_calculation')));
+
+// Calculate Course Total
+if ($course_total->calculation) {
+    // Course Total is calculated
+    $ct_params = build_params($items, $course_total->calculation);
+    $ct_value = number_format(use_formula($course_total->calculation, $ct_params), 2);
+} else {
+    // Course Total is aggregated
+    $categories[$course_total->id] = $course_total;
+    $agg_return = aggregate_category($items, $course_total->id, $categories, true); 
+    $agg_grade = $agg_return[0];
+    $extra_credit = $agg_return[1];
+
+    if ($course_total->aggregation != GRADE_AGGREGATE_SUM) {
+        $ct_value = grade_grade::standardise_score($agg_grade, 0, 1, 
+            $course_total->grademin, $course_total->grademax);
+    } else {
+        $ct_value = $agg_grade;
+    }
+
+    $ct_value += $extra_credit;
+    $ct_value = number_format($ct_value, 2);
+}
+
+// NEW 03/11/08
+// Fix for percentage display bug
+$ct_value = grade_format_gradevalue($ct_value, $course_total, true, $course_total->display, $course_total->decimals);
+
+echo prepare_response_string($items) . '|calc_total_grade=<b>' . $ct_value . '</b>';
+
+?>
Index: grade/report/simple_grader/lib/simple_grade_hook.php
===================================================================
RCS file: grade/report/simple_grader/lib/simple_grade_hook.php
diff -N grade/report/simple_grader/lib/simple_grade_hook.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/lib/simple_grade_hook.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,374 @@
+<?php // $Id: simple_grade_hook.php,v 1.0 2008-05-14 17:03:46 pcali1 Exp $
+
+require_once($CFG->libdir . '/grade/grade_grade.php');
+require_once($CFG->libdir . '/grade/constants.php');
+require_once('simple_gradelib.php');
+require_once('grade_sql.php');
+
+
+/**
+ * Special processing used for quick edit course grade items
+ */
+function course_quick_process($data, $courseid) {
+    //explode on _ for each grade item
+    $course_items = get_real_grades($courseid, true);
+
+    $members = get_object_vars($data);
+
+    foreach ($course_items as $item) {
+        $grade_max = (float) $members[$item->id.'_max_value'];
+        $curve_to = (float) $members[$item->id.'_curve_to'];
+
+        $is_xc = isset($members[$item->id.'_extra_credit']);
+        $agg_holder = ((!$is_xc && $members[$item->id.'_item_weight'] == 0) ? 1 : $members[$item->id.'_item_weight']);
+
+        $aggregationcoef = ($is_xc ? 0 : $agg_holder);
+ 
+        $multfactor = ($curve_to == 0) ? 1 : $curve_to/$grade_max;
+
+        $grade_item = grade_item::fetch(array('id' => $item->id, 'courseid'=>$courseid));
+        $grade_item->grademax = $grade_max;
+        $grade_item->multfactor = $multfactor;
+        $grade_item->aggregationcoef = $aggregationcoef;
+       
+        $grade_item->update();
+ 
+        $grade_item->set_parent($members[$item->id . '_selector']);
+    }
+}
+
+/**
+ * The process data function is ripped out of lib.php so both quickedit
+ * screens the the actual report can the same processing function
+ */
+function process_data($data, $courseid, $mode='grades', $fieldid=0) {
+        $warnings = array();
+
+        // always initialize all arrays
+        $queue = array();
+        foreach ($data as $varname => $postedvalue) {
+
+            $needsupdate = false;
+
+            // skip, not a grade nor feedback
+            if (strpos($varname, 'grade') === 0) {
+                $data_type = 'grade';
+            } else if (strpos($varname, 'feedback') === 0) {
+                $data_type = 'feedback';
+            } else if (strpos($varname, 'override') === 0) {
+                $data_type = 'override'; 
+            } else if (strpos($varname, 'exclude') === 0 ){
+                $data_type = 'exclude';
+            } else if (strpos($varname, 'adjustvalue') === 0 ){
+                $data_type = 'adjustments';
+            } else {
+                continue;
+            }
+
+            $gradeinfo = explode("_", $varname);
+            $userid = clean_param($gradeinfo[1], PARAM_INT);
+            $itemid = clean_param($gradeinfo[2], PARAM_INT);
+
+            $oldvalue = $data->{'old'.$varname};
+
+            if ($data_type == 'adjustments') {
+                $adjustment_value = $data->{'adjustgrade_'.$userid.'_'.$itemid} 
+                . $data->{'adjustvalue_'.$userid.'_'.$itemid};
+                $postedvalue = (float) $adjustment_value;
+            }
+
+            // was change requested?
+            if ($oldvalue == $postedvalue) { // string comparison
+                continue;
+            }
+
+            if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) { // we must verify course id here!
+                error('Incorrect grade item id');
+            }
+
+            // Pre-process grade
+            if ($data_type == 'grade') {
+                $feedback = false;
+                $feedbackformat = false;
+                if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+                    if ($postedvalue == -1) { // -1 means no grade
+                        $finalgrade = null;
+                    } else {
+                        $finalgrade = $postedvalue;
+                    }
+                } else {
+                    $finalgrade = unformat_float($postedvalue);
+                }
+
+                $errorstr = '';
+                // Warn if the grade is out of bounds.
+                if (is_null($finalgrade)) {
+                    // ok
+                } else if ($finalgrade < $grade_item->grademin) {
+                    $errorstr = 'lessthanmin';
+                } else if ($finalgrade > $grade_item->grademax*2) {
+                    $errorstr = 'morethanmax';
+                }
+                if ($errorstr) {
+                    $user = get_record('user', 'id', $userid, '', '', '', '', 'id, firstname, lastname');
+                    $gradestr = new object();
+
+                    if ($mode == 'anonymous') {            
+                        $gradestr->username = get_field_select('user_info_data', 'data', 
+                            "userid={$user->id} AND fieldid={$fieldid}");
+                    } else {
+                        $gradestr->username = fullname($user);
+                    }
+                    $gradestr->itemname = $grade_item->get_name();
+                    $warnings[] = get_string($errorstr, 'grades', $gradestr);
+                }
+
+            } else if ($data_type == 'feedback') {
+                $finalgrade = false;
+                $trimmed = trim($postedvalue);
+                if (empty($trimmed)) {
+                     $feedback = NULL;
+                } else {
+                     $feedback = stripslashes($postedvalue);
+                }
+            } else if ($data_type == 'override') { 
+               $grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$userid));
+               $grade->grade_item = &$grade_item;
+                
+               $old_overridden = $grade->overridden;
+               $grade->set_overridden($postedvalue);
+               
+               if ($old_overridden != $grade->overridden) {
+                   $grade_item->force_regrading();
+               }
+               continue;
+            } else if ($data_type == 'exclude' and $mode!= 'anonymous') {
+               $grade = new grade_grade(array('itemid'=>$itemid, 'userid'=>$userid));
+               $grade->grade_item = &$grade_item;
+
+               $old_excluded = $grade->excluded;
+               $grade->set_excluded($postedvalue);
+
+               if ($old_excluded != $grade->excluded){
+                   $parent = $grade_item->get_parent_category();
+                   $parent->force_regrading();
+               }
+               continue;
+            } else if ($data_type == 'adjustments') {
+                if ($enable_features = get_field('block_anonymous_grade_config', 'value', 'name', 'enable_features')) {
+                    $max_adjusted_value = get_field('block_anonymous_grade_config', 'value', 'name', 'max_adjust_value');
+                    $min_adjusted_value = -1 * $max_adjusted_value;
+                    if ($postedvalue < $min_adjusted_value || $postedvalue > $max_adjusted_value) {
+                        $warnings[] = "Adjustments value is not within the specified range";
+                        continue;
+                    }
+                } else {
+                    continue;
+                }
+
+                if ($item = get_record('block_anon_grade_adjustments', 'userid', $userid, 'itemid', $itemid)) {
+                    $adjustment = $item;
+                } else {
+                    $adjustment = new stdClass;
+                }
+
+                $adjustment->itemid = $itemid;
+                $adjustment->userid = $userid;
+                $adjustment->adjust_value = $postedvalue;
+
+                if ($grade = get_field('grade_grades', 'finalgrade', 'itemid', $itemid, 'userid', $userid)) {
+                    if (!isset($adjustment->grade_before)) {
+                        $adjustment->grade_before = $grade;
+                    }
+                    $finalgrade = $adjustment->grade_before + $adjustment->adjust_value;
+                }
+
+                if($adjustment->id) {
+                    update_record('block_anon_grade_adjustments', $adjustment);
+                } else {
+                    insert_record('block_anon_grade_adjustments', $adjustment);
+                }
+            }
+            
+            
+            if($mode == 'anonymous') {
+                store_anonymous_grades($data_type, $postedvalue, $grade_item, $userid);
+            } else {            
+                simple_update_final_grade($userid, $grade_item, 2, $finalgrade, 'gradebook', $feedback, FORMAT_MOODLE);
+            }
+
+        }
+        return $warnings;
+}
+
+/**
+ *  This function "cleans" out the gradecategory if it switched between categories
+ *  The idea is: if they switched from sum to weighted mean, the aggregationcoef
+ *  would reflect the changes in the database. Also, fixed a potential bug with the
+ *  grademax still inflated when switching from sum aggregation to weighted mean.
+ */
+function clean_aggregation_switch($grade_category) {
+
+    if ($grade_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+        $grade_category->grade_item->grademax = format_float(100, 5);
+        $grade_category->grade_item->update();
+    }
+    
+    //$grade_items = $grade_category->get_children();
+    /*foreach($grade_items as $gid=>$grade_item){
+        if ($grade_item['type'] == 'category') {
+            $item = $grade_item['object']->get_grade_item();
+        } else {
+            $item = $grade_item['object'];
+        }
+        $weight = (float)$item->aggregationcoef;
+        if ($weight < 1.0000 && $weight > 0.0000) {
+            $item->aggregationcoef = format_float(1,5);
+        }    
+        $item->update();
+    }*/
+}
+
+function derive_sum_max($parent_category) {
+    // Cache the category's grade item
+    $cat_item = $parent_category->get_grade_item();
+
+    $children = $parent_category->get_children();
+   
+    $max = 0;
+    //find max grade
+    foreach ($children as $sortorder=>$items) {
+        $item = $items['object'];
+        if ($item->aggregationcoef <= 0) {
+            // extra credit from this activity - does not affect total
+            continue;
+        }
+        if ($item->gradetype == GRADE_TYPE_VALUE) {
+            $max += $item->grademax;
+        } else if ($item->gradetype == GRADE_TYPE_SCALE) {
+            $max += $item->grademax - 1; // scales min is 1
+        }
+    }
+    
+    if ($cat_item->grademax != $max or $cat_item->grademin != 0 or $cat_item->gradetype != GRADE_TYPE_VALUE){
+        $cat_item->grademax = $max;
+        $cat_item->grademin = 0;
+        $cat_item->gradetype = GRADE_TYPE_VALUE;
+        $cat_item->update('aggregation');
+    }
+    
+}
+
+/**
+ * As the function names states, is takes the anonymous grade in the anonymous grade table
+ * and moves them out to the mdl_grade_grades table, making them vulnerable to agg methods
+ * and such
+ */
+function move_fake_grades_to_real($itemid, $courseid) {
+    $grade_item = grade_item::fetch(array('id' => $itemid, 'courseid' => $courseid));
+    $grades = get_records('block_anon_grade_grades', 'itemid', $itemid);
+
+
+    foreach($grades as $grade) {
+        //make sure we finalize the adjustment before moving the grades into the real table
+        if ($adjustment = get_record('block_anon_grade_adjustments', 'userid', $grade->userid, 'itemid', $itemid)) {
+            $adjustment->grade_before = $grade->finalgrade;
+            $grade->finalgrade += $adjustment->adjust_value;
+            update_record('block_anon_grade_adjustments', $adjustment);
+        }
+
+        simple_update_final_grade($grade->userid, $grade_item, 2, $grade->finalgrade, 'gradebook', $grade->feedback, FORMAT_MOODLE);
+        // Maybe call a delete record, for the anonymous grade (clean up)
+        // TODO, definitely something worth discussing
+    }
+}
+
+/**
+ * Function that stores grades posted in the anonymous quick edit screen in the anonymous grade table
+ */
+function store_anonymous_grades($data_type, $postedvalue, $item, $userid) {
+    if ($data_type == "adjustments") {
+        return;
+    }    
+
+    global $USER;
+
+    if ($grade_grade = get_record('block_anon_grade_grades', 'itemid', $item->id, 'userid', $userid)){
+        $grade = $grade_grade;
+    } else {
+        $grade = new stdClass;
+    }
+
+    switch ($data_type) {
+        case "grade":
+            $grade->finalgrade = bounded_number($item->grademin, $postedvalue, $item->grademax * 2);
+            break;
+        case "feedback":
+            $grade->feedback = $postedvalue;
+            break;
+        case "exclude":
+            $grade->excluded = $postedvalue;
+            break;
+    }
+    $grade->itemid = $item->id;
+    $grade->userid = $userid;
+    $grade->usermodified = $USER->id;
+    $grade->timemodified = time();
+    $grade->feedbackformat = FORMAT_MOODLE;
+    
+    if ($grade->id) {
+        update_record('block_anon_grade_grades', $grade);
+    } else {
+        $grade->timecreated = time();
+        insert_record('block_anon_grade_grades', $grade);
+    }
+}
+
+/**
+ * Return a string to an icon location; used in quick_edit, where items must be either mod or manual
+ */
+function get_element_icon($element) {
+    global $CFG;
+    if ($element->itemtype == 'mod') {
+        return '<img src="'.$CFG->pixpath.'/mod/'.$element->itemmodule.'/icon.gif" alt=""/>';
+    } else {
+        return '<img src="'.$CFG->pixpath.'/t/manual_item.gif" alt=""/>';
+    }
+}
+
+/**
+ * This function returns the "overlib" variant of the user profile image
+ * Replaces print_user_picture in the report, and is used in the quick edit screens
+ */
+function custom_user_image($user) {
+   global $CFG; 
+ 
+   if ($user->picture) {
+       $imagelink = '<img onmouseout="return nd()" onmouseover="return overlib(profile_image(\''.
+     $CFG->wwwroot.'\', \''.$user->id.'\'), CAPTION, \''.fullname($user).'\')" src="'.
+     $CFG->wwwroot.'/user/pix.php/'.$user->id.'/f2.jpg" ';
+  } else {
+     $imagelink = '<img src="'.$CFG->pixpath.'/u/f2.png"';
+  }
+  $imagelink .= ' alt="Picture of '. fullname($user). '"/>';
+  return $imagelink;
+}
+
+// This is a temporary copy of most of simple_category_sum_grades.
+// Projected Final Grade needs the calculated grade, but does not need to update
+// the final grade in the database.
+// TODO: Separate the summation of the grade from the database insertion, and have 
+//       former call the latter rather than couple the two actions.
+function simple_category_get_sum($grade_category, $items, $grade_values, $multiplier=2) {
+        //Determine the grade max
+        $max = simple_determine_grademax($grade_category, $items, $grade_values);
+
+        $sum = array_sum($grade_values);
+        $finalgrade = bounded_number(0, $sum, $max * $multiplier);
+
+        return $finalgrade;
+}
+
+
+
+?>
Index: grade/edit/simple_tree/lang/en_utf8/help/grade/anonymous.html
===================================================================
RCS file: grade/edit/simple_tree/lang/en_utf8/help/grade/anonymous.html
diff -N grade/edit/simple_tree/lang/en_utf8/help/grade/anonymous.html
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/lang/en_utf8/help/grade/anonymous.html	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,4 @@
+<h1>Anonymous Grade Item</h1>
+<p>Teachers who create anonymous grade items cannot know the name of the user they are grading. This is done to protect the identity of those graded users. <br />
+Known grade items can not be made into anonymous grade items. Anonymous grade items will only be made known when all students are graded. <br />
+Adjustments are limited by the system administrator and can be edited at any time.</p>
Index: grade/report/simple_grader/styles_ie6.css
===================================================================
RCS file: grade/report/simple_grader/styles_ie6.css
diff -N grade/report/simple_grader/styles_ie6.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/styles_ie6.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,20 @@
+/**
+ * Author: Robert Russo
+ */
+.grade-report-simple_grader form {
+  text-align: left;
+}
+
+.grade-report-simple_grader div.left_scroller {
+  margin-top: 40px;
+}
+
+.grade-report-simple_grader div.right_scroller {
+  margin-top: 40px;
+  width: auto;
+  position: absolute;
+}
+
+.excludedfloater {
+  font-size: 7px;
+}
Index: grade/edit/custom_letter/lettermenufixer.php
===================================================================
RCS file: grade/edit/custom_letter/lettermenufixer.php
diff -N grade/edit/custom_letter/lettermenufixer.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/lettermenufixer.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,33 @@
+<script type="text/javascript">
+//<![CDATA[
+function ReplaceObj(orig_text, replace_text) {
+    this.replacement = replace_text;
+    this.original = orig_text;
+}
+
+ReplaceObj.prototype.doReplace = function (originalString){
+    return originalString.replace(this.original, this.replacement);
+}
+
+function replace_plugin(){
+	var selector = document.getElementById('choosepluginreport_jump');
+
+	if(selector !=null) {
+        var search_values = new Array(
+                            new ReplaceObj('edit/tree', 'edit/simple_tree'),
+                            new ReplaceObj('edit/letter', 'edit/custom_letter'));
+        
+	    for (var i =0; i< selector.options.length; i++){
+                for (var j=0; j<search_values.length; j++){
+                var replaceObj = search_values[j];
+            
+    			if(selector.options[i].value.search(replaceObj.original)) {
+	    		    selector.options[i].value = replaceObj.doReplace(selector.options[i].value);
+    		    }
+            }
+		}
+	}
+}
+
+//]]>
+</script>
Index: grade/edit/simple_tree/outcomeitem_form.php
===================================================================
RCS file: grade/edit/simple_tree/outcomeitem_form.php
diff -N grade/edit/simple_tree/outcomeitem_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/outcomeitem_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,246 @@
+<?php  //$Id: outcomeitem_form.php,v 1.12.2.12 2008-03-22 21:25:39 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once $CFG->libdir.'/formslib.php';
+
+class edit_outcomeitem_form extends moodleform {
+    function definition() {
+        global $COURSE, $CFG;
+
+        $mform =& $this->_form;
+
+/// visible elements
+        $mform->addElement('header', 'general', get_string('gradeoutcomeitem', 'grades'));
+
+        $mform->addElement('text', 'itemname', get_string('itemname', 'grades'));
+        $mform->addRule('itemname', get_string('required'), 'required', null, 'client');
+
+        $mform->addElement('text', 'iteminfo', get_string('iteminfo', 'grades'));
+        $mform->setHelpButton('iteminfo', array('iteminfo', get_string('iteminfo', 'grades'), 'grade'), true);
+
+        $mform->addElement('text', 'idnumber', get_string('idnumbermod'));
+        $mform->setHelpButton('idnumber', array('idnumber', get_string('idnumber', 'grades'), 'grade'), true);
+
+        // allow setting of outcomes on module items too
+        $options = array();
+        if ($outcomes = grade_outcome::fetch_all_available($COURSE->id)) {
+            foreach ($outcomes as $outcome) {
+                $options[$outcome->id] = $outcome->get_name();
+            }
+        }
+        $mform->addElement('select', 'outcomeid', get_string('outcome', 'grades'), $options);
+        $mform->setHelpButton('outcomeid', array('outcomeid', get_string('outcomeid', 'grades'), 'grade'), true);
+        $mform->addRule('outcomeid', get_string('required'), 'required');
+
+        $options = array(0=>get_string('none'));
+        if ($coursemods = get_course_mods($COURSE->id)) {
+            foreach ($coursemods as $coursemod) {
+                $mod = get_coursemodule_from_id($coursemod->modname, $coursemod->id);
+                $options[$coursemod->id] = format_string($mod->name);
+            }
+        }
+        $mform->addElement('select', 'cmid', get_string('linkedactivity', 'grades'), $options);
+        $mform->setHelpButton('cmid', array('linkedactivity', get_string('linkedactivity', 'grades'), 'grade'), true);
+        $mform->setDefault('cmid', 0);
+
+        /*$mform->addElement('text', 'gradepass', get_string('gradepass', 'grades'));
+        $mform->setHelpButton('gradepass', array(false, get_string('gradepass', 'grades'),
+                false, true, false, get_string('gradepasshelp', 'grades')));*/
+
+        /// hiding
+        /// advcheckbox is not compatible with disabledIf !!
+        $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades'));
+        $mform->setHelpButton('hidden', array('hidden', get_string('hidden', 'grades'), 'grade'));
+        $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('hiddenuntil', array('hiddenuntil', get_string('hiddenuntil', 'grades'), 'grade'));
+        $mform->disabledIf('hidden', 'hiddenuntil[off]', 'notchecked');
+
+        //locking
+        $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades'));
+        $mform->setHelpButton('locked', array('locked', get_string('locked', 'grades'), 'grade'));
+        $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('locktime', array('lockedafter', get_string('locktime', 'grades'), 'grade'));
+
+/// parent category related settings
+        $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades'));
+
+        $options = array();
+        $default = '';
+        $coefstring = '';
+        $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id));
+        foreach ($categories as $cat) {
+            $cat->apply_forced_settings();
+            $options[$cat->id] = $cat->get_name();
+            if ($cat->is_course_category()) {
+                $default = $cat->id;
+            }
+            if ($cat->is_aggregationcoef_used()) {
+                if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                    $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefweight') ? 'aggregationcoefweight' : 'aggregationcoef';
+
+                } else if ($cat->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
+                    $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextra') ? 'aggregationcoefextra' : 'aggregationcoef';
+
+                } else if ($cat->aggregation == GRADE_AGGREGATE_SUM) {
+                    $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextrasum') ? 'aggregationcoefextrasum' : 'aggregationcoef';
+
+                } else {
+                    $coefstring = 'aggregationcoef';
+                }
+            } else {
+                $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id);
+            }
+        }
+
+        if (count($categories) > 1) {
+            $mform->addElement('select', 'parentcategory', get_string('gradecategory', 'grades'), $options);
+            $mform->disabledIf('parentcategory', 'cmid', 'noteq', 0);
+        }
+
+        if ($coefstring !== '') {
+            if ($coefstring == 'aggregationcoefextrasum') {
+                // advcheckbox is not compatible with disabledIf!
+                $mform->addElement('checkbox', 'aggregationcoef', get_string($coefstring, 'grades'));
+            } else {
+                $mform->addElement('text', 'aggregationcoef', get_string($coefstring, 'grades'));
+            }
+            $mform->setHelpButton('aggregationcoef', array($coefstring, get_string($coefstring, 'grades'), 'grade'), true);
+        }
+
+/// hidden params
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'courseid', $COURSE->id);
+        $mform->setType('courseid', PARAM_INT);
+
+/// add return tracking info
+        $gpr = $this->_customdata['gpr'];
+        $gpr->add_mform_elements($mform);
+
+/// mark advanced according to site settings
+        if (isset($CFG->grade_item_advanced)) {
+            $advanced = explode(',', $CFG->grade_item_advanced);
+            foreach ($advanced as $el) {
+                if ($mform->elementExists($el)) {
+                    $mform->setAdvanced($el);
+                }
+            }
+        }
+//-------------------------------------------------------------------------------
+        // buttons
+        $this->add_action_buttons();
+    }
+
+
+/// tweak the form - depending on existing data
+    function definition_after_data() {
+        global $CFG, $COURSE;
+
+        $mform =& $this->_form;
+
+        if ($id = $mform->getElementValue('id')) {
+            $grade_item = grade_item::fetch(array('id'=>$id));
+
+            //remove the aggregation coef element if not needed
+            if ($grade_item->is_course_item()) {
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->removeElement('parentcategory');
+                }
+                if ($mform->elementExists('aggregationcoef')) {
+                    $mform->removeElement('aggregationcoef');
+                }
+
+            } else {
+                // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!!
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->hardFreeze('parentcategory');
+                }
+
+                if ($grade_item->is_category_item()) {
+                    $category = $grade_item->get_item_category();
+                    $parent_category = $category->get_parent_category();
+                } else {
+                    $parent_category = $grade_item->get_parent_category();
+                }
+
+                $parent_category->apply_forced_settings();
+
+                if (!$parent_category->is_aggregationcoef_used() or $parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+                    if ($mform->elementExists('aggregationcoef')) {
+                        $mform->removeElement('aggregationcoef');
+                    }
+                } else {
+                    //fix label if needed
+                    $agg_el =& $mform->getElement('aggregationcoef');
+                    $aggcoef = '';
+                    if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                        $aggcoef = 'aggregationcoefweight';
+
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
+                        $aggcoef = 'aggregationcoefextra';
+
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+                        $aggcoef = 'aggregationcoefextrasum';
+                    }
+
+                    if ($aggcoef !== '') {
+                        $agg_el->setLabel(get_string($aggcoef, 'grades'));
+                        $mform->setHelpButton('aggregationcoef', array($aggcoef, get_string($aggcoef, 'grades'), 'grade'));
+                    }
+                }
+            }
+
+        }
+
+        // no parent header for course category
+        if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) {
+            $mform->removeElement('headerparent');
+        }
+    }
+
+
+/// perform extra validation before submission
+    function validation($data, $files) {
+        global $COURSE;
+
+        $errors = parent::validation($data, $files);
+
+        if (array_key_exists('idnumber', $data)) {
+            if ($data['id']) {
+                $grade_item = new grade_item(array('id'=>$data['id'], 'courseid'=>$data['courseid']));
+            } else {
+                $grade_item = null;
+            }
+            if (!grade_verify_idnumber($data['idnumber'], $COURSE->id, $grade_item, null)) {
+                $errors['idnumber'] = get_string('idnumbertaken');
+            }
+        }
+
+        return $errors;
+    }
+
+}
+?>
Index: grade/report/simple_grader/styles.php
===================================================================
RCS file: grade/report/simple_grader/styles.php
diff -N grade/report/simple_grader/styles.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/styles.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,499 @@
+/**
+ * Author: Robert Russo
+ */
+
+.grade-report-simple_grader table {
+  border-collapse: collapse;
+  background-color: #ffffff;
+  font-size: 10px;
+  border-color: #cecece;
+}
+
+
+.grade-report-simple_grader .r1 {
+  background-color: #ffffff;
+}
+
+.grade-report-simple_grader .flexible th, .grade-report-simple_grader .flexible td {
+  white-space: nowrap;
+}
+
+.grade-report-simple_grader .flexible th a, .grade-report-simple_grader .flexible td a {
+  white-space: nowrap;
+}
+
+.grade-report-simple_grader th {
+  padding: 10px;
+}
+
+.grade-report-simple_grader span.inclusion-links {
+   margin: 0 5px 0 10px;
+}
+
+.grade-report-simple_grader .gradestable th.user, .grade-report-simple_grader .gradestable th.range, .grade-report-simple_grader td {
+    white-space: nowrap;
+}
+
+.grade-report-simple_grader table#user-grades .catlevel1 {
+  background-color: #ffffff;
+}
+
+.grade-report-simple_grader table#user-grades .catlevel2 {
+  background-color: #f9f9f9;
+}
+
+.grade-report-simple_grader table#user-grades .catlevel3 {
+  background-color: #efefef;
+}
+
+.grade-report-simple_grader table#user-grades .item {
+  background-color: #e9e9e9;
+}
+
+.grade-report-simple_grader table#user-grades td.overridden {
+  background-color: #dddddd;
+}
+
+.grade-report-simple_grader table tr.odd td.cell {
+    background-color: #efefef;
+}
+
+.grade-report-simple_grader table tr.even td.cell {
+    background-color: #ffffff;
+}
+
+.grade-report-simple_grader table tr.even th {
+    background-color: #ffffff;
+}
+
+.grade-report-simple_grader table tr.odd th.header { 
+    background-color: #efefef;
+    border-width: 0px 0px 1px 0px;
+    background-image: none;
+}
+
+.grade-report-simple_grader table tr.heading th.header {
+    border-top: 1px solid #cecece;
+}
+
+.grade-report-simple_grader table#user-grades tr.heading th.categoryitem,
+.grade-report-simple_grader table#user-grades tr.heading th.courseitem {
+  border-width: 0px 0px 0px 1px;
+}
+
+.grade-report-simple_grader table#user-grades td.vmarked, .grade-report-simple_grader table#user-grades tr.odd td.vmarked {
+    background-color: #ffcc33;
+}
+
+.grade-report-simple_grader table#user-grades td.hmarked, .grade-report-simple_grader table#user-grades tr.odd td.hmarked {
+    background-color: #ffff99;
+}
+
+.grade-report-simple_grader table#user-grades td.hmarked.vmarked, .grade-report-simple_grader table#user-grades tr.odd td.hmarked.vmarked{
+    background-color: #ffcc99;
+} 
+
+.grade-report-simple_grader table tr.avg td.cell {
+background-color: #f3ead8;
+}   
+    
+.grade-report-simple_grader table#user-grades tr.groupavg td.cell {
+  font-weight: bold;
+  color: #006400;
+}
+
+.grade-report-simple_grader table#user-grades tr.avg td.cell {
+  font-weight: bold;
+  color: #00008B;
+}
+
+.grade-report-simple_grader table#user-grades td.cat,
+.grade-report-simple_grader table#user-grades td.course {
+  font-weight: bold;
+}
+
+.grade-report-simple_grader table#user-grades {
+  border-width: 1px;
+  border-style: solid;
+  font-size: 10px;
+  margin: 0;
+  margin-top: 20px;
+  width: auto;
+  background-color: transparent;
+}
+
+.grade-report-simple_grader #overDiv table {
+  margin: 0;  
+}
+
+.grade-report-simple_grader #overDiv table td.feedback {
+  border: 0px;
+}
+.grade-report-simple_grader #overDiv .feedback {
+  background-color: #AABBFF;
+  color: #000000;
+  font-family: Verdana;
+  font-weight: normal;  
+}
+
+.grade-report-simple_grader #overDiv .caption {
+  background-color: #5566CC;
+  color: #CCCCFF;
+  font-family: Arial;
+  font-weight: bold;
+}
+
+.grade-report-simple_grader div.submit {
+  margin-top: 20px;
+ text-align: center;
+}
+
+.grade-report-simple_grader table#user-grades td {
+  border-width: 0px 1px 1px 0px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades tr.heading {
+  border-width:0px 0px 0px 0px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades .heading td {
+  border-width:0px 0px 0px 0px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades th.category {
+  border-width:1px 1px 0px 1px;
+  border-style:solid;
+  vertical-align: top;
+}
+
+.grade-report-simple_grader table#user-grades th.category.header.catlevel1 {
+  border-width: 1px 1px 0px 0px;
+  border-style:solid;
+  vertical-align: top;
+}
+
+.grade-report-simple_grader table#user-grades th.user {
+  border-width:0px 0px 1px 0px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades th.useridnumber {
+  border-width:0px 0px 1px 1px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader div.left_scroller tr {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader div.right_scroller tr {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader div.left_scroller td {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader div.right_scroller td {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader div.left_scroller th {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader div.left_scroller th.user a {
+  vertical-align: middle;
+  margin: 0;
+  padding: 0;
+}
+
+.grade-report-simple_grader div.right_scroller th {
+  height: 4em;
+  font-size: 10px;
+}
+
+.grade-report-simple_grader table#user-grades th.categoryitem,
+.grade-report-simple_grader table#user-grades th.courseitem,
+.grade-report-simple_grader table td.topleft {
+  border-width: 0px 1px 1px 1px;
+  border-style: solid;
+  border-color: #cecece;
+  vertical-align: top;
+}
+
+.grade-report-simple_grader table#user-grades td.topleft {
+  background-color: transparent;
+}
+
+.grade-report-simple_grader table#participants th {
+  vertical-align: top; 
+  width: auto;
+}
+
+.grade-report-simple_grader table#user-grades td.fillerfirst {
+  border-width:0px 0px 0px 1px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades td.fillerlast {
+  border-width:0px 1px 0px 0px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader table#user-grades th.item {
+  border-width:1px 1px 1px 1px;
+  border-style:solid;
+  vertical-align: top;
+}
+
+.grade-report-simple_grader div.gradertoggle {
+  display: inline;
+  margin-left: 20px;
+}
+
+.grade-report-simple_grader table#user-grades th {
+ text-align: left;
+}
+
+.grade-report-simple_grader table th.user {
+ text-align: left;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader table td.useridnumber {
+ text-align:left;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader table#user-grades td {
+ text-align: right;
+}
+
+.grade-report-simple_grader table#user-grades th.range {
+  border-width:1px 1px 1px 1px;
+  border-style:solid;
+}
+
+.grade-report-simple_grader div.userpic {
+  margin-right: 10px;
+  float: left;
+}
+
+.grade-report-simple_grader div.userpic img {
+  border: 3px double #cecece;
+  vertical-align: middle;
+  width: 2.7em;
+  height: 2.7em;
+}
+
+
+.grade-report-simple_grader table#user-grades .quickfeedback {
+  border: #000000 1px dashed;
+}
+
+.grade-report-simple_grader #siteconfiglink {
+ text-align: right;
+}
+
+.grade-report-simple_grader table#user-grades .hidden,
+.grade-report-simple_grader table#user-grades .hidden a {
+  color:#aaaaaa;
+}
+
+.grade-report-simple_grader table#user-grades .datesubmitted {
+  font-size: 0.7em;
+}
+
+.grade-report-simple_grader table#user-grades td.cell {
+  padding-left: 5px;
+  padding-right: 5px;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader a.quickedit {
+  line-height: 1em;
+  display: block;
+  float: right;
+  margin: .1em 0 0 0;
+  clear: none;
+  font-size: 9px;
+  background-color: transparent;
+}
+
+.grade-report-simple_grader a.quickedit2 {
+  display: block;
+  float: right;
+  margin: 1.3em 0 0 0;
+  clear: none;
+  background-color: transparent;
+}
+
+.grade-report-simple_grader table#quick_edit {
+  margin: 0 auto 0 auto;
+  border: 1px solid #cecece;
+}
+
+.grade-report-simple_grader table#quick_edit td {
+  vertical-align: middle;
+  padding: 0;
+  margin: 0;
+  border: 1px solid #cecece;
+  text-align: left;
+}
+
+.grade-report-simple_grader table#quick_edit td img {
+  border: 3px double #cecece;
+  padding: 0;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader td input {
+  border: 1px solid #666666;
+  margin-left: 10px;
+  margin-right: 10px;
+}
+
+.grade-report-simple_grader table#quick_edit td {
+  padding: 5px;
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+.grade-report-simple_grader table#quick_edit td.fullname {
+border-left: none;
+padding-left: 5px;
+}
+
+.grade-report-simple_grader table#quick_edit td.picture {
+border-right: none;
+}
+
+.grade-report-simple_grader table#quick_edit td.finalgrade input {
+width: 5em;
+}
+
+.grade-report-simple_grader h1 {
+ text-align: center;
+  clear: both;
+}
+
+.grade-report-simple_grader form {
+text-align: center;
+}
+
+.grade-report-simple_grader input.center {
+  margin: 10px auto 0 auto;
+}
+
+.grade-report-simple_grader .lefttbody {
+  width: auto;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader table#user-grades th.fixedcolumn {
+  border: 1px solid #cecece;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader table#fixes_column th {
+  border: 1px solid #cecece;
+  vertical-align: middle;
+}
+
+.grade-report-simple_grader table#fixes_column {
+  padding-top: 20px;
+  border-top: 1px solid #cecece;
+  background-color: #ffffff;
+}
+
+.grade-report-simple_grader .left_scroller {
+  float: left;
+  clear: none;
+  padding-top: 20px;
+}
+
+.grade-report-simple_grader .right_scroller {
+  width: auto;
+  clear: none;
+  overflow-x: auto;
+}
+
+.grade-report-simple_grader th {
+  padding-top: 2px;
+  padding-bottom: 0;
+}
+
+.grade-report-simple_grader .controls_row th {
+  background-color: #f3ead8;
+}
+
+.grade-report-simple_grader table tr.avg, .grade-report-simple_grader table tr.avg td, .grade-report-simple_grader table tr.avg th, .grade-report-simple_grader table tr.controls_row, .grade-report-simple_grader table tr.controls_row th, .grade-report-simple_grader table tr.range_row, .grade-report-simple_grader table tr.range_row th {
+  height: 2em;
+}
+
+.grade-report-simple_grader table tr.avg, .grade-report-simple_grader table tr.avg td, .grade-report-simple_grader table tr.avg th {
+background-color: #f3ead8;
+}
+
+.grade-report-simple_grader table#user-grades tr.groupavg td.cell, .grade-report-simple_grader tr.groupavg th.header {
+    background-color: #efffef;
+}
+
+.grade-report-simple_grader div.gradeparent {
+ text-align: left;
+}
+
+.grade-report-simple_grader form td.excluded {
+  color: #ff0000;
+}
+
+.grade-report-simple_grader form .excludedfloater {
+  float: left;
+}
+
+.grade-report-simple_grader .excludedfloater {
+  font-weight: bold;
+  color: #ff0000;
+  font-size: 9px;
+}
+
+.grade-report-simple_grader span.gradepass {
+    color: #298721;
+}
+
+.grade-report-simple_grader span.gradefail {
+    color: #890d0d;
+}
+
+.gradeweight {
+color: #461d7c;
+font-weight: bold;
+}
+
+.biguserpic {
+width: 100%;
+}
+
+.fullgradestable {
+    font-size: 120%;
+}
+
+
+.grade-report-simple_grader td select {
+font-size: 100%;
+padding: 0;
+}
+
+.grade-report-simple_grader .righttest td select {
+font-size: 86%;
+padding: 0;
+}
Index: grade/import/mymathlab/index.php
===================================================================
RCS file: grade/import/mymathlab/index.php
diff -N grade/import/mymathlab/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/import/mymathlab/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @author Adam Zapletal
+ * Louisiana State University
+ */
+
+require_once('../../../config.php');
+require_once $CFG->dirroot.'/grade/lib.php';
+
+///////////////////////////////////////////////////////////////////////////////
+
+$id = required_param('id', PARAM_INT); // course id
+
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_login($course);
+
+echo require_js(array('yui_yahoo', 'yui_dom-event', 'yui_animation', 'yui_event', 
+                      'yui_connection', 'functions.js'));
+
+$context = get_context_instance(CONTEXT_COURSE, $id);
+
+require_capability('moodle/grade:import', $context);
+require_capability('gradeimport/mymathlab:view', $context);
+
+// Add our stylesheet
+$CFG->stylesheets[] = $CFG->wwwroot . '/grade/import/mymathlab/style.css';
+
+$actionstr = get_string('modulename', 'gradeimport_mymathlab');
+$navigation = grade_build_nav(__FILE__, $actionstr, array('courseid' => $course->id));
+
+print_header($course->shortname.': '.get_string('grades'), $course->fullname, $navigation);
+print_grade_plugin_selector($id, 'import', 'mymathlab');
+
+///////////////////////////////////////////////////////////////////////////////
+
+$action = 'mapping.php?id=' . $course->id;
+
+// Echo file upload form
+echo '
+<div id = "error" class = "error">&nbsp;</div>
+<form enctype = "multipart/form-data" action = "' . $action . 
+'" method = "post" onsubmit = "return validate_index();">
+<input type = "hidden" name = "MAX_FILE_SIZE" value = "1000000"/>
+
+<div class = "upload_form">
+    <div class = "upload_row">
+        <span class = "file_label">' . get_string('file', 'gradeimport_mymathlab') . ':</span>
+        <input name = "mymathlab_file" class = "file_upload" type = "file"/>
+    </div>
+    <input class="submit_button" type="submit" value = "' . get_string('upload', 'gradeimport_mymathlab') . '"/>
+</div>
+</form>';
+
+///////////////////////////////////////////////////////////////////////////////
+
+print_footer();
+
+?>
Index: blocks/anonymous_grade/lib.php
===================================================================
RCS file: blocks/anonymous_grade/lib.php
diff -N blocks/anonymous_grade/lib.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/lib.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * This is a lib file that external applications can use to interact with anonymous grades
+ */
+
+
+/**
+ * Provided an anonymous number, this function will return the user that number matches
+ * @param $anonymous_number  Anonymous number in question
+ * @param $select_str Provide a dumbed down user field of interest
+ */
+function anonymous_to_user_sql($anonymous_number, $select_str="u.*") {
+    global $CFG;
+    
+    if (!$select_str) {
+        $select_str = "u.*";
+    }
+
+    $sql = 'SELECT '. $select_str . " FROM {$CFG->prefix}user u, 
+                                {$CFG->prefix}user_info_data ud 
+                    WHERE u.id = ud.userid 
+                    AND ud.data='{$anonymous_number}'";
+
+    return get_record_sql($sql);
+}
+
+
+/**
+ * Provided an array of anonymous numbers, the function will return an array of corresponding user info
+ * @param $anonymous_numbers  Array of anonymous numbers
+ */
+function anonymous_numbers_to_real_user_ids($anonymous_numbers) {
+    global $CFG;
+
+    $real_users = array();
+    foreach ($anonymous_numbers as $number) {
+        $user = anonymous_to_user_sql($number, 'u.id');
+        $real_users[$number] = $user->id;
+    }
+
+    return $real_users;
+}
+
+/**
+ * Provided grade values and an array of items, this function
+ * will return the raw extra credit score for the category in question
+ */
+function get_category_extra_credit_score($grade_values, $items) {
+    $extra_credit = 0;
+        
+    if (!get_field('block_anonymous_grade_config', 'value', 'name', 'enable_features') == '0'
+      && get_field('block_anonymous_grade_config', 'value', 'name', 'extra_credit') == '0') {
+        return $extra_credit;
+    }
+
+
+    foreach ($grade_values as $itemid => $grade_value) {
+        if ($items[$itemid]->aggregationcoef <= 0) {
+            $extra_credit += (float)$grade_value * (float)$items[$itemid]->grademax;
+        }
+    }    
+
+    return $extra_credit;
+}
+
+?>
Index: grade/edit/custom_letter/edit.php
===================================================================
RCS file: grade/edit/custom_letter/edit.php
diff -N grade/edit/custom_letter/edit.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/custom_letter/edit.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,147 @@
+<?php // $Id: edit.php,v 1.3.2.2 2008-05-09 07:40:54 rrusso Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require '../../../config.php';
+require_once $CFG->libdir.'/gradelib.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once 'edit_form.php';
+
+
+$contextid = optional_param('id', SYSCONTEXTID, PARAM_INT);
+
+if (!$context = get_context_instance_by_id($contextid)) {
+    error('Incorrect context id');
+}
+
+if ($context->contextlevel == CONTEXT_SYSTEM or $context->contextlevel == CONTEXT_COURSECAT) {
+    require_once $CFG->libdir.'/adminlib.php';
+    require_login();
+    admin_externalpage_setup('custom_letter');
+    $admin = true;
+    $returnurl = "$CFG->wwwroot/grade/edit/custom_letter/edit.php"; // stay in the same page
+
+
+} else if ($context->contextlevel == CONTEXT_COURSE) {
+    require_login($context->instanceid);
+    $admin = false;
+    $returnurl = $CFG->wwwroot.'/grade/edit/custom_letter/index.php?id='.$context->instanceid;
+
+} else {
+    error('Incorrect context level');
+}
+
+require_capability('moodle/grade:manageletters', $context);
+
+$strgrades = get_string('grades');
+$pagename  = get_string('letters', 'grades');
+
+$letters = grade_get_letters($context);
+$num = count($letters) + 3;
+
+$data = new object();
+$data->id = $context->id;
+
+$i = 1;
+foreach ($letters as $boundary=>$letter) {
+    $gradelettername = 'gradeletter'.$i;
+    $gradeboundaryname = 'gradeboundary'.$i;
+
+    $data->$gradelettername   = $letter;
+    $data->$gradeboundaryname = $boundary;
+    $i++;
+}
+$data->override = record_exists('grade_letters', 'contextid', $contextid);
+
+$mform = new edit_letter_form(null, array('num'=>$num, 'admin'=>$admin));
+$mform->set_data($data);
+
+if ($mform->is_cancelled()) {
+    redirect($returnurl);
+
+} else if ($data = $mform->get_data()) {
+    if (!$admin and empty($data->override)) {
+        delete_records('grade_letters', 'contextid', $context->id);
+        redirect($returnurl);
+    }
+
+    $letters = array();
+    for($i=1; $i<$num+1; $i++) {
+        $gradelettername = 'gradeletter'.$i;
+        $gradeboundaryname = 'gradeboundary'.$i;
+
+        if (array_key_exists($gradeboundaryname, $data) and $data->$gradeboundaryname != '') {
+            $letter = trim($data->$gradelettername);
+            if ($letter == '') {
+                continue;
+            }
+            $letters[$data->$gradeboundaryname] = $letter;
+        }
+    }
+    krsort($letters, SORT_NUMERIC);
+
+    $old_ids = array();
+    if ($records = get_records('grade_letters', 'contextid', $context->id, 'lowerboundary ASC', 'id')) {
+        $old_ids = array_keys($records);
+    }
+
+    foreach($letters as $boundary=>$letter) {
+        $record = new object();
+        $record->letter        = $letter;
+        $record->lowerboundary = $boundary;
+        $record->contextid     = $context->id;
+
+        if ($old_id = array_pop($old_ids)) {
+            $record->id = $old_id;
+            update_record('grade_letters', $record);
+        } else {
+            insert_record('grade_letters', $record);
+        }
+    }
+
+    foreach($old_ids as $old_id) {
+        delete_records('grade_letters', 'id', $old_id);
+    }
+
+    redirect($returnurl);
+}
+
+
+//page header
+if ($admin) {
+    admin_externalpage_print_header();
+
+} else {
+    $navigation = grade_build_nav(__FILE__, $pagename, $COURSE->id);
+    /// Print header
+    print_header_simple($strgrades.': '.$pagename, ': '.$strgrades, $navigation, '', '', true, '', navmenu($COURSE));
+
+    $currenttab = 'lettersedit';
+    require('tabs.php');
+}
+
+$mform->display();
+
+print_footer($COURSE);
+?>
Index: blocks/anonymous_grade/settings.php
===================================================================
RCS file: blocks/anonymous_grade/settings.php
diff -N blocks/anonymous_grade/settings.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/settings.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,7 @@
+<?php
+
+    $link = '<a href="'.$CFG->wwwroot.'/blocks/anonymous_grade/enable.php">'.
+        get_string('extra_features', 'block_anonymous_grade'). '</a>';
+    $settings->add(new admin_setting_heading('block_anonymous_grade_config', '', $link));
+
+?>
Index: grade/edit/simple_tree/category_form.php
===================================================================
RCS file: grade/edit/simple_tree/category_form.php
diff -N grade/edit/simple_tree/category_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/category_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,290 @@
+<?php  //$Id: category_form.php,v 1.9.2.14 2008-03-22 21:19:09 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once $CFG->libdir.'/formslib.php';
+
+class edit_category_form extends moodleform {
+
+    function definition() {
+        global $CFG, $COURSE;
+        $mform =& $this->_form;
+
+        $options = array(
+                         GRADE_AGGREGATE_WEIGHTED_MEAN   =>get_string('aggregateweightedmean', 'grades'),
+                         GRADE_AGGREGATE_WEIGHTED_MEAN2  =>get_string('aggregateweightedmean2', 'grades'),
+                         GRADE_AGGREGATE_SUM             =>get_string('aggregatesum', 'grades'));
+
+        // visible elements
+        $mform->addElement('header', 'headercategory', get_string('gradecategory', 'grades'));
+        $mform->addElement('text', 'fullname', get_string('categoryname', 'grades'));
+        $mform->addRule('fullname', null, 'required', null, 'client');
+
+        $mform->addElement('select', 'aggregation', get_string('aggregation', 'grades'), $options);
+        $mform->setHelpButton('aggregation', array('simple_aggregation', get_string('aggregation', 'grades'), 'grade'));
+        $mform->disabledIf('droplow', 'aggregation', 'eq', GRADE_AGGREGATE_SUM);
+        $mform->disabledIf('keephigh', 'aggregation', 'eq', GRADE_AGGREGATE_SUM);
+        if ((int)$CFG->grade_aggregation_flag & 2) {
+            $mform->setAdvanced('aggregation');
+        }
+
+        $mform->addElement('checkbox', 'aggregateonlygraded', get_string('aggregateonlygraded', 'gradereport_simple_grader'));
+        $mform->setHelpButton('aggregateonlygraded', array('simple_aggregateonlygraded', get_string('aggregateonlygraded', 'grades'),'grade'), true);
+        $mform->disabledIf('aggregateonlygraded', 'aggregation', 'eq', GRADE_AGGREGATE_SUM);
+        if ((int)$CFG->grade_aggregateonlygraded_flag & 2) {
+            $mform->setAdvanced('aggregateonlygraded');
+        }
+
+        if (empty($CFG->enableoutcomes)) {
+            $mform->addElement('hidden', 'aggregateoutcomes');
+            $mform->setType('aggregateoutcomes', PARAM_INT);
+        } else {
+            $mform->addElement('checkbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades'));
+            $mform->setHelpButton('aggregateoutcomes', array('aggregateoutcomes', get_string('aggregateoutcomes', 'grades'), 'grade'), true);
+            if ((int)$CFG->grade_aggregateoutcomes_flag & 2) {
+                $mform->setAdvanced('aggregateoutcomes');
+            }
+        }
+
+        $options = array(0 => get_string('all'));
+        for ($i=1; $i<=100; $i++) {
+            $options[$i] = $i;
+        }
+        $drop_options = $options;
+        $drop_options[0] = get_string('none');
+
+        $mform->addElement('select', 'keephigh', get_string('keephigh', 'grades'), $options);
+        $mform->setHelpButton('keephigh', array('keephigh', get_string('keephigh', 'grades'), 'grade'), true);
+        if ((int)$CFG->grade_keephigh_flag & 2) {
+            $mform->setAdvanced('keephigh');
+        }
+
+        $mform->addElement('select', 'droplow', get_string('droplow', 'grades'), $drop_options);
+        $mform->setHelpButton('droplow', array('droplow', get_string('droplow', 'grades'), 'grade'), true);
+        $mform->disabledIf('droplow', 'keephigh', 'noteq', 0);
+        if ((int)$CFG->grade_droplow_flag & 2) {
+            $mform->setAdvanced('droplow');
+        }
+
+        $mform->disabledIf('keephigh', 'droplow', 'noteq', 0);
+        $mform->disabledIf('droplow', 'keephigh', 'noteq', 0);
+
+/// parent category related settings
+        $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades'));
+
+        $options = array();
+        $default = '';
+        $coefstring = '';
+        $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id));
+        foreach ($categories as $cat) {
+            $cat->apply_forced_settings();
+            $options[$cat->id] = $cat->get_name();
+            if ($cat->is_course_category()) {
+                $default = $cat->id;
+            }
+            if ($cat->is_aggregationcoef_used()) {
+                $coefstring = 'aggregationcoefweight';
+                if ($cat->aggregation == GRADE_AGGREGATE_SUM) {
+                    $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id);
+                }
+                /*if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                    $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefweight') ? 'aggregationcoefweight' : 'aggregationcoef';
+                } else {
+                    $coefstring = 'aggregationcoef';
+                }*/
+            } else {
+                $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id);
+            }
+        }
+        if (count($categories) > 1) {
+            $mform->addElement('select', 'parentcategory', get_string('gradecategory', 'grades'), $options);
+        }
+
+        if ($coefstring !== '') {
+            $mform->addElement('text', 'aggregationcoef', get_string($coefstring, 'grades'));
+            $mform->setHelpButton('aggregationcoef', array('aggregationcoef', get_string('aggregationcoef', 'grades'), 'grade'), true);
+        }
+
+/// user preferences
+        $mform->addElement('header', 'headerpreferences', get_string('myreportpreferences', 'grades'));
+        $options = array(GRADE_REPORT_PREFERENCE_DEFAULT => get_string('default', 'grades'),
+                         GRADE_REPORT_AGGREGATION_VIEW_FULL => get_string('fullmode', 'grades'),
+                         GRADE_REPORT_AGGREGATION_VIEW_AGGREGATES_ONLY => get_string('aggregatesonly', 'grades'),
+                         GRADE_REPORT_AGGREGATION_VIEW_GRADES_ONLY => get_string('gradesonly', 'grades'));
+        $label = get_string('aggregationview', 'grades') . ' (' . get_string('default', 'grades')
+               . ': ' . $options[$CFG->grade_report_aggregationview] . ')';
+        $mform->addElement('select', 'pref_aggregationview', $label, $options);
+        $mform->setHelpButton('pref_aggregationview', array('aggregationview', get_string('aggregationview', 'grades'), 'grade'), true);
+        $mform->setDefault('pref_aggregationview', GRADE_REPORT_PREFERENCE_DEFAULT);
+        $mform->setAdvanced('pref_aggregationview');
+
+        // hidden params
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'courseid', 0);
+        $mform->setType('courseid', PARAM_INT);
+
+/// add return tracking info
+        $gpr = $this->_customdata['gpr'];
+        $gpr->add_mform_elements($mform);
+
+//-------------------------------------------------------------------------------
+        // buttons
+        $this->add_action_buttons();
+    }
+
+
+/// tweak the form - depending on existing data
+    function definition_after_data() {
+        global $CFG, $COURSE;
+
+        $mform =& $this->_form;
+
+        $somecat = new grade_category();
+        foreach ($somecat->forceable as $property) {
+            if ((int)$CFG->{"grade_{$property}_flag"} & 1) {
+                if ($mform->elementExists($property)) {
+                    if (empty($CFG->grade_hideforcedsettings)) {
+                        $mform->hardFreeze($property);
+                    } else {
+                        if ($mform->elementExists($property)) {
+                            $mform->removeElement($property);
+                        }
+                    }
+                }
+            }
+        }
+
+        if ($CFG->grade_droplow > 0) {
+            if ($mform->elementExists('keephigh')) {
+                $mform->removeElement('keephigh');
+            }
+        } else if ($CFG->grade_keephigh > 0) {
+            if ($mform->elementExists('droplow')) {
+                $mform->removeElement('droplow');
+            }
+        }
+
+        if ($id = $mform->getElementValue('id')) {
+            $grade_category = grade_category::fetch(array('id'=>$id));
+            $grade_item = $grade_category->load_grade_item();
+
+
+            // remove agg coef if not used
+            if ($grade_category->is_course_category()) {
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->removeElement('parentcategory');
+                }
+                if ($mform->elementExists('aggregationcoef')) {
+                    $mform->removeElement('aggregationcoef');
+                }
+
+            } else {
+                // if we wanted to change parent of existing category - we would have to verify there are no circular references in parents!!!
+                if ($mform->elementExists('parentcategory')) {
+                    $mform->hardFreeze('parentcategory');
+                }
+
+                $parent_category = $grade_category->get_parent_category();
+                $parent_category->apply_forced_settings();
+                if (!$parent_category->is_aggregationcoef_used()) {
+                    if ($mform->elementExists('aggregationcoef')) {
+                        $mform->removeElement('aggregationcoef');
+                    }
+                } else {
+                    //fix label if needed
+                    $agg_el =& $mform->getElement('aggregationcoef');
+                    $aggcoef = '';
+                    if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
+                        $aggcoef = 'aggregationcoefweight';
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
+                        $aggcoef = 'aggregationcoefextra';
+                    } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
+                        //$mform->hardFreeze('aggregationcoef');
+                        $mform->removeElement('aggregationcoef');
+                    }
+                    if ($aggcoef !== '') {
+                        $agg_el->setLabel(get_string($aggcoef, 'grades'));
+                        $mform->setHelpButton('aggregationcoef', array('aggregationcoef', get_string('aggregationcoef', 'grades'), 'grade'), true);
+                    }
+                }
+                
+            }
+
+            if ($grade_item->is_calculated()) {
+                // following elements are ignored when calculation formula used
+                if ($mform->elementExists('aggregation')) {
+                    $mform->removeElement('aggregation');
+                }
+                if ($mform->elementExists('keephigh')) {
+                    $mform->removeElement('keephigh');
+                }
+                if ($mform->elementExists('droplow')) {
+                    $mform->removeElement('droplow');
+                }
+                if ($mform->elementExists('aggregateonlygraded')) {
+                    $mform->removeElement('aggregateonlygraded');
+                }
+                if ($mform->elementExists('aggregateoutcomes')) {
+                    $mform->removeElement('aggregateoutcomes');
+                }
+                if ($mform->elementExists('aggregatesubcats')) {
+                    $mform->removeElement('aggregatesubcats');
+                }
+            }
+
+            if ($grade_category->aggregation == GRADE_AGGREGATE_SUM) {
+
+                if ($mform->elementExists('keephigh')) {
+                    $mform->removeElement('keephigh');
+                }
+                if ($mform->elementExists('droplow')) {
+                    $mform->removeElement('droplow');
+                }
+            }
+            
+            // If it is a course category, remove the "required" rule from the "fullname" element
+            if ($grade_category->is_course_category()) {
+                unset($mform->_rules['fullname']);
+                $key = array_search('fullname', $mform->_required);
+                unset($mform->_required[$key]);
+                $mform->hardFreeze('fullname');
+            }
+
+            // If it is a course category and its fullname is ?, show an empty field
+            if ($grade_category->is_course_category() && $mform->getElementValue('fullname') == '?') {
+                $mform->setDefault('fullname', $COURSE->fullname);
+            } 
+        }
+
+        // no parent header for course category
+        if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) {
+            $mform->removeElement('headerparent');
+        }
+
+    } 
+}
+
+?>
Index: grade/export/csv/lang/en_utf8/gradeexport_csv.php
===================================================================
RCS file: grade/export/csv/lang/en_utf8/gradeexport_csv.php
diff -N grade/export/csv/lang/en_utf8/gradeexport_csv.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/lang/en_utf8/gradeexport_csv.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,8 @@
+<?PHP // $Id: gradeexport_csv.php,v 1.0 2008-06-26 13:43:00 rrusso Exp $
+
+$string['modulename'] = 'CSV Exporter';
+$string['csv:view'] = 'Use CSV grade export';
+$string['csv:publish'] = 'Publish CSV grade export';
+
+?>
+
Index: grade/export/csv/dump.php
===================================================================
RCS file: grade/export/csv/dump.php
diff -N grade/export/csv/dump.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/export/csv/dump.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,46 @@
+<?php  //$Id: dump.php,v 1.5 2007-10-10 06:34:22 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$nomoodlecookie = true; // session not used here
+require '../../../config.php';
+
+$id = required_param('id', PARAM_INT); // course id
+if (!$course = get_record('course', 'id', $id)) {
+    print_error('nocourseid');
+}
+
+require_user_key_login('grade/export', $id); // we want different keys for each course
+
+if (empty($CFG->gradepublishing)) {
+    error('Grade publishing disabled');
+}
+
+$context = get_context_instance(CONTEXT_COURSE, $id);
+require_capability('gradeexport/csv:publish', $context);
+
+// use the same page parameters as export.php and append &key=sdhakjsahdksahdkjsahksadjksahdkjsadhksa
+require 'export.php';
+
+?>
Index: grade/report/projected/settings.php
===================================================================
RCS file: grade/report/projected/settings.php
diff -N grade/report/projected/settings.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/settings.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,35 @@
+<?php // $Id: settings.php,v 1.1.2.4 2007-10-30 21:41:42 skodak Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas  http://dougiamas.com     //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/// Add settings for this module to the $settings object (it's already defined)
+
+//$settings->add(new admin_setting_configcheckbox('grade_report_projected_showrank', get_string('showrank', 'grades'), get_string('configshowrank', 'grades'), 0, PARAM_INT));
+
+$options = array(0 => get_string('shownohidden', 'grades'),
+                 1 => get_string('showhiddenuntilonly', 'grades'),
+                 2 => get_string('showallhidden', 'grades'));
+$settings->add(new admin_setting_configselect('grade_report_projected_showhiddenitems', get_string('showhiddenitems', 'grades'), get_string('configshowhiddenitems', 'grades'), 1, $options));
+
+?>
Index: grade/report/simple_grader/settings.php
===================================================================
RCS file: grade/report/simple_grader/settings.php
diff -N grade/report/simple_grader/settings.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/settings.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,132 @@
+<?php // $Id: settings.php,v 1.34.2.6 2008-03-03 07:27:07 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards Martin Dougiamas  http://dougiamas.com     //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+$strinherit             = get_string('inherit', 'grades');
+$strpercentage          = get_string('percentage', 'grades');
+$strreal                = get_string('real', 'grades');
+$strletter              = get_string('letter', 'grades');
+$strinherit             = get_string('inherit', 'grades');
+
+/// Add settings for this module to the $settings object (it's already defined)
+$settings->add(new admin_setting_configtext('grade_report_simple_studentsperpage', get_string('studentsperpage', 'grades'),
+                                        get_string('configstudentsperpage', 'grades'), 100));
+
+/**
+ * Edited by: Philip Cali (pcali1)
+ * Added sticky tab support
+ */
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showstickytab', get_string('showstickytab', 'gradereport_simple_grader'),
+                    get_string('configshowstickytab', 'gradereport_simple_grader'), 1));
+
+
+//Removed because it confused teachers
+//$settings->add(new admin_setting_configcheckbox('grade_report_simple_quickgrading', get_string('quickgrading', 'grades'),
+//                                            get_string('configquickgrading', 'grades'), 1));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showquickfeedback', get_string('quickfeedback', 'grades'),
+                                            get_string('configshowquickfeedback', 'grades'), 0));
+
+$settings->add(new admin_setting_configselect('grade_report_simple_aggregationview', get_string('aggregationview', 'grades'),
+                                          get_string('configaggregationview', 'grades'), GRADE_REPORT_AGGREGATION_VIEW_FULL,
+                                          array(GRADE_REPORT_AGGREGATION_VIEW_FULL => get_string('full', 'grades'),
+                                                GRADE_REPORT_AGGREGATION_VIEW_AGGREGATES_ONLY => get_string('aggregatesonly', 'grades'),
+                                                GRADE_REPORT_AGGREGATION_VIEW_GRADES_ONLY => get_string('gradesonly', 'grades'))));
+
+$settings->add(new admin_setting_configselect('grade_report_simple_meanselection', get_string('meanselection', 'grades'),
+                                          get_string('configmeanselection', 'grades'), GRADE_REPORT_MEAN_GRADED,
+                                          array(GRADE_REPORT_MEAN_ALL => get_string('meanall', 'grades'),
+                                                GRADE_REPORT_MEAN_GRADED => get_string('meangraded', 'grades'))));
+
+// $settings->add(new admin_setting_configcheckbox('grade_report_enableajax', get_string('enableajax', 'grades'),
+//                                            get_string('configenableajax', 'grades'), 0));
+
+// Edited by: Philip Cali (pcali1)
+// Removed for simplicity's sake
+//$settings->add(new admin_setting_configcheckbox('grade_report_showcalculations', get_string('showcalculations', 'grades'),
+//                                            get_string('configshowcalculations', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showeyecons', get_string('showeyecons', 'grades'),
+                                           get_string('configshoweyecons', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showaverages', get_string('showaverages', 'grades'),
+                                            get_string('configshowaverages', 'grades'), 1));
+
+// Edited by: Philip Cali (pcali1)
+// Always show group selector
+//$settings->add(new admin_setting_configcheckbox('grade_report_showgroups', get_string('showgroups', 'grades'),
+                                            //get_string('configshowgroups', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showlocks', get_string('showlocks', 'grades'),
+                                            get_string('configshowlocks', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showranges', get_string('showranges', 'grades'),
+                                            get_string('configshowranges', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showuserimage', get_string('showuserimage', 'grades'),
+                                            get_string('configshowuserimage', 'grades'), 1));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showuseridnumber', get_string('showuseridnumber', 'grades'),
+                                            get_string('configshowuseridnumber', 'grades'), 0));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_showactivityicons', get_string('showactivityicons', 'grades'),
+                                            get_string('configshowactivityicons', 'grades'), 1));
+
+$settings->add(new admin_setting_configcheckbox('grade_report_simple_shownumberofgrades', get_string('shownumberofgrades', 'grades'),
+                                            get_string('configshownumberofgrades', 'grades'), 0));
+
+$settings->add(new admin_setting_configselect('grade_report_simple_averagesdisplaytype', get_string('averagesdisplaytype', 'grades'),
+                                          get_string('configaveragesdisplaytype', 'grades'), GRADE_REPORT_PREFERENCE_INHERIT,
+                                          array(GRADE_REPORT_PREFERENCE_INHERIT => $strinherit,
+                                                GRADE_DISPLAY_TYPE_REAL => $strreal,
+                                                GRADE_DISPLAY_TYPE_PERCENTAGE => $strpercentage,
+                                                GRADE_DISPLAY_TYPE_LETTER => $strletter)));
+
+$settings->add(new admin_setting_configselect('grade_report_simple_rangesdisplaytype', get_string('rangesdisplaytype', 'grades'),
+                                          get_string('configrangesdisplaytype', 'grades'), GRADE_REPORT_PREFERENCE_INHERIT,
+                                          array(GRADE_REPORT_PREFERENCE_INHERIT => $strinherit,
+                                                GRADE_DISPLAY_TYPE_REAL => $strreal,
+                                                GRADE_DISPLAY_TYPE_PERCENTAGE => $strpercentage,
+                                                GRADE_DISPLAY_TYPE_LETTER => $strletter)));
+
+$settings->add(new admin_setting_configselect('grade_report_simple_averagesdecimalpoints', get_string('averagesdecimalpoints', 'grades'),
+                                          get_string('configaveragesdecimalpoints', 'grades'), GRADE_REPORT_PREFERENCE_INHERIT,
+                                          array(GRADE_REPORT_PREFERENCE_INHERIT => $strinherit,
+                                                 '0' => '0',
+                                                 '1' => '1',
+                                                 '2' => '2',
+                                                 '3' => '3',
+                                                 '4' => '4',
+                                                 '5' => '5')));
+$settings->add(new admin_setting_configselect('grade_report_simple_rangesdecimalpoints', get_string('rangesdecimalpoints', 'grades'),
+                                          get_string('configrangesdecimalpoints', 'grades'), GRADE_REPORT_PREFERENCE_INHERIT,
+                                          array(GRADE_REPORT_PREFERENCE_INHERIT => $strinherit,
+                                                 '0' => '0',
+                                                 '1' => '1',
+                                                 '2' => '2',
+                                                 '3' => '3',
+                                                 '4' => '4',
+                                                 '5' => '5')));
+
+?>
Index: grade/edit/simple_tree/grade_form.php
===================================================================
RCS file: grade/edit/simple_tree/grade_form.php
diff -N grade/edit/simple_tree/grade_form.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/edit/simple_tree/grade_form.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,203 @@
+<?php  //$Id: grade_form.php,v 1.10.2.3 2008-03-03 10:21:41 nicolasconnault Exp $
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+require_once $CFG->libdir.'/formslib.php';
+
+class edit_grade_form extends moodleform {
+
+    function definition() {
+        global $CFG, $COURSE;
+
+        $mform =& $this->_form;
+
+        $grade_item = $this->_customdata['grade_item'];
+        $gpr        = $this->_customdata['gpr'];
+
+        /// information fields
+        $mform->addElement('static', 'user', get_string('user'));
+        $mform->addElement('static', 'itemname', get_string('itemname', 'grades'));
+
+        $mform->addElement('checkbox', 'overridden', get_string('overridden', 'grades'));
+        $mform->setHelpButton('overridden', array('overridden', get_string('overridden', 'grades'), 'grade'));
+
+        /// actual grade - numeric or scale
+        if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
+            // numeric grade
+            $mform->addElement('text', 'finalgrade', get_string('finalgrade', 'grades'));
+            $mform->setHelpButton('finalgrade', array('finalgrade', get_string('finalgrade', 'grades'), 'grade'));
+            $mform->disabledIf('finalgrade', 'overridden', 'notchecked');
+
+        } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
+            // scale grade
+            $scaleopt = array();
+
+            if (empty($grade_item->outcomeid)) {
+                $scaleopt[-1] = get_string('nograde');
+            } else {
+                $scaleopt[-1] = get_string('nooutcome', 'grades');
+            }
+
+            $i = 1;
+            if ($scale = get_record('scale', 'id', $grade_item->scaleid)) {
+                foreach (split(",", $scale->scale) as $option) {
+                    $scaleopt[$i] = $option;
+                    $i++;
+                }
+            }
+
+            $mform->addElement('select', 'finalgrade', get_string('finalgrade', 'grades'), $scaleopt);
+            $mform->setHelpButton('finalgrade', array('finalgrade', get_string('finalgrade', 'grades'), 'grade'));
+            $mform->disabledIf('finalgrade', 'overridden', 'notchecked');
+        }
+
+        $mform->addElement('advcheckbox', 'excluded', get_string('excluded', 'grades'));
+        $mform->setHelpButton('excluded', array('excluded', get_string('excluded', 'grades'), 'grade'));
+
+        /// hiding
+        /// advcheckbox is not compatible with disabledIf !!
+        $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades'));
+        $mform->setHelpButton('hidden', array('hidden', get_string('hidden', 'grades'), 'grade'));
+        $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('hiddenuntil', array('hiddenuntil', get_string('hiddenuntil', 'grades'), 'grade'));
+        $mform->disabledIf('hidden', 'hiddenuntil[off]', 'notchecked');
+
+        /// locking
+        $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades'));
+        $mform->setHelpButton('locked', array('locked', get_string('locked', 'grades'), 'grade'));
+        $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true));
+        $mform->setHelpButton('locktime', array('lockedafter', get_string('locktime', 'grades'), 'grade'));
+        $mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE);
+
+        // Feedback format is automatically converted to html if user has enabled editor
+        $mform->addElement('htmleditor', 'feedback', get_string('feedback', 'grades'),
+            array('rows'=>'15', 'course'=>$COURSE->id, 'cols'=>'45'));
+        $mform->setHelpButton('feedback', array('feedback', get_string('feedback', 'grades'), 'grade'));
+        $mform->setType('text', PARAM_RAW); // to be cleaned before display, no XSS risk
+        $mform->addElement('format', 'feedbackformat', get_string('format'));
+        $mform->setHelpButton('feedbackformat', array('textformat', get_string('helpformatting')));
+        //TODO: unfortunately we can not disable html editor for external grades when overridden off :-(
+
+        // hidden params
+        $mform->addElement('hidden', 'oldgrade');
+        $mform->addElement('hidden', 'oldfeedback');
+
+        $mform->addElement('hidden', 'id', 0);
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'itemid', 0);
+        $mform->setType('itemid', PARAM_INT);
+
+        $mform->addElement('hidden', 'userid', 0);
+        $mform->setType('userid', PARAM_INT);
+
+        $mform->addElement('hidden', 'courseid', $COURSE->id);
+        $mform->setType('courseid', PARAM_INT);
+
+/// add return tracking info
+        $gpr->add_mform_elements($mform);
+
+//-------------------------------------------------------------------------------
+        // buttons
+        $this->add_action_buttons();
+    }
+
+    function definition_after_data() {
+        global $CFG, $COURSE;
+
+        $context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
+
+        $mform =& $this->_form;
+        $grade_item = $this->_customdata['grade_item'];
+        $grade_category = $grade_item->get_parent_category();
+
+        // fill in user name if user still exists
+        $userid = $mform->getElementValue('userid');
+        if ($user = get_record('user', 'id', $userid)) {
+            $username = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'">'.fullname($user).'</a>';
+            $user_el =& $mform->getElement('user');
+            $user_el->setValue($username);
+        }
+
+        // add activity name + link
+        if ($grade_item->itemtype == 'mod') {
+            $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid);
+            $itemname = '<a href="'.$CFG->wwwroot.'/mod/'.$grade_item->itemmodule.'/view.php?id='.$cm->id.'">'.$grade_item->get_name().'</a>';
+        } else {
+            $itemname = $grade_item->get_name();
+        }
+        $itemname_el =& $mform->getElement('itemname');
+        $itemname_el->setValue($itemname);
+
+        // access control - disable not allowed elements
+        if (!has_capability('moodle/grade:manage', $context) or $grade_category->aggregation == GRADE_AGGREGATE_SUM) {
+            $mform->hardFreeze('excluded');
+        }
+
+        if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
+            $mform->hardFreeze('hidden');
+            $mform->hardFreeze('hiddenuntil');
+        }
+
+        $old_grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid));
+
+        if (!$grade_item->is_overridable_item()) {
+            $mform->removeElement('overridden');
+        }
+
+        if ($grade_item->is_hidden()) {
+            $mform->hardFreeze('hidden');
+        }
+
+        if ($old_grade_grade->is_locked()) {
+            if ($grade_item->is_locked()) {
+                $mform->hardFreeze('locked');
+                $mform->hardFreeze('locktime');
+            }
+
+            $mform->hardFreeze('overridden');
+            $mform->hardFreeze('finalgrade');
+            $mform->hardFreeze('feedback');
+
+        } else {
+            if (empty($old_grade_grade->id)) {
+                $old_grade_grade->locked = $grade_item->locked;
+                $old_grade_grade->locktime = $grade_item->locktime;
+            }
+
+            if (($old_grade_grade->locked or $old_grade_grade->locktime)
+              and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) {
+                $mform->hardFreeze('locked');
+                $mform->hardFreeze('locktime');
+
+            } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime)
+              and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) {
+                $mform->hardFreeze('locked');
+                $mform->hardFreeze('locktime');
+            }
+        }
+    }
+}
+
+?>
Index: grade/report/simple_grader/styles_ie.css
===================================================================
RCS file: grade/report/simple_grader/styles_ie.css
diff -N grade/report/simple_grader/styles_ie.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/styles_ie.css	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,8 @@
+/**
+ * Author: Robert Russo
+ */
+
+.grade-report-simple_grader .right_scroller {
+  padding-bottom: 15px;
+  overflow-y: hidden;
+}
Index: grade/report/projected/projected.js
===================================================================
RCS file: grade/report/projected/projected.js
diff -N grade/report/projected/projected.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/projected/projected.js	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,191 @@
+// @author Adam Zapletal
+// February 27, 2008
+
+// Add in_array to array objects
+Array.prototype.in_array = function(value) {
+    if (null == value) {
+        return false;
+    }
+
+    for(var i = 0; i < this.length; i++) {
+        if(this[i] == value) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+// Add a keyup listener to all text inputs that represent empty grades
+function addListeners() {
+    var x = document.getElementsByTagName("input");
+    for(var i = 0; i < x.length; i++) {
+        if(x[i].type == 'text' && x[i].id.substring(5, 0) == 'calc_') {
+            YAHOO.util.Event.addListener(x[i].id, "keyup", interceptKeypress, x[i]);
+        }
+    }
+}
+
+// Number of milliseconds to wait before sending a request.
+interval = 250;
+lastKeypress = null;
+
+// Waits to make sure the user doesn't press another key quickly after the first.
+// Without this function, the script would send many unnecessary requests.
+// Example: The user is trying to input 100, this function makes sure that it only
+// sends a request for 100 rather than 1, 10, and 100.
+// Adapted from code by Brad Harris @ 
+// http://selfcontained.us/2007/10/07/ajax-requests-when-users-stop-typing/
+function interceptKeypress(e, elem) {
+    lastKeypress = new Date().getTime();
+    var errorElem = document.getElementById('error');
+
+        if (validInput(elem.value, e) && checkRanges()) {
+            elem.style.backgroundColor = '#FFFFFF';
+            errorElem.innerHTML = '<br />';
+
+            setTimeout(function() {
+                var currentTime = new Date().getTime();
+        
+                if (currentTime - lastKeypress > interval) {
+                    handleEvent(e, elem);
+                }
+            }, interval + 100);
+        } else if (e.keyCode > 64 && e.keyCode < 91 && !modifierDown(e)) {
+            errorElem.innerHTML = '<center>Invalid Grade: ' + elem.value + '</center>';
+            elem.style.backgroundColor = '#FF6666';
+        }
+}
+
+// Checks that the input value is within the range allowed by it's corresponding
+// grade item.
+function inRange(id) {
+    // Get minmax and input values from page
+    var minmax = document.getElementById('minmax_' + id).value.split('|');
+    var value = document.getElementById('calc_grade_' + id).value;
+
+    if(!(value >= parseFloat(minmax[0])) || !(value <= parseFloat(minmax[1]))) {
+        return minmax;
+    } else {
+        return false;
+    }
+}
+
+// Iterates over all text inputs and checks that their values are in range.
+// If not, the error div is filled with a meaningful message.
+function checkRanges() {
+    var inputs = document.getElementsByTagName('input');
+    var errorElem =  document.getElementById('error');
+
+    for(var i = 0; i < inputs.length; i++) {
+        if(inputs[i].type == 'text') {
+            var tmp = inputs[i].id.split('_');
+            var rangeError;
+
+            if(inputs[i].value != '') {
+                rangeError = inRange(tmp[2]);
+            }
+            
+            if(rangeError) {
+                var s = '';
+                s  = '<center>Range Error: Expected '
+                s += Math.round(rangeError[0]) + '-' 
+                s += Math.round(rangeError[1]) + '</center>';
+                errorElem.innerHTML = s;
+                inputs[i].style.backgroundColor = '#FF6666';
+
+                return false;
+            } else {
+                errorElem.innerHTML = s;
+                inputs[i].style.backgroundColor = '#FFFFFF';
+            }
+        }
+    }
+
+    return true;
+}
+
+// Checks that value is either a number or backspace with no modifier keys down
+function validInput(value, e) {
+    return ((numberPressed(e) || e.keyCode == 8 || e.keyCode == 46) && !modifierDown(e)) ? true : false;
+}
+
+// Array for numpad keycodes
+var numpadKeys = new Array(96, 97, 98, 99, 100, 101, 102, 103, 104, 105); 
+
+// Checks for numerical value
+function numberPressed(e) {
+    return isFinite(parseInt(String.fromCharCode(e.keyCode))) || numpadKeys.in_array(e.keyCode);
+}
+
+// Checks for control, windows || command, shift, and alt keys being down 
+function modifierDown(e) {
+    return (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey); 
+}
+
+// Aggregates input data and makes the ajax request
+function handleEvent(e, elem) {
+    var errorElem =  document.getElementById('error');
+
+    // Sets the error div to blank because if we are here, input is valid
+    errorElem.innerHTML = '<br />';
+    elem.style.backgroundColor = '#FFFFFF';
+      
+    var inputs = document.getElementsByTagName('input');
+    var inputdata = '';
+    var fieldval;
+    var first = true;
+
+    for(var i = 0; i < inputs.length; i++) {
+        if(inputs[i].type == 'text') {
+            if(!first) {
+                inputdata += '|';
+            }
+
+            fieldval = (inputs[i].value == '') ? 'switch_me' : inputs[i].value;
+            inputdata += inputs[i].id + '=' + fieldval;
+            first = false;
+        }
+    }
+
+    makeRequest(inputdata);
+}
+
+// Parses the request's return string and fills calculated and aggregated
+// fields with values.
+var handleSuccess = function(o) {
+    if(o.responseText !== undefined) {
+        var parts = o.responseText.split('|');
+        for(var i = 0; i < parts.length; i++) {
+            var tmp = parts[i].split('=');
+            var elem = document.getElementById(tmp[0]);
+            if(elem != null) {
+                elem.innerHTML = tmp[1];
+            }
+        }
+    }
+}
+
+// Failure case, report mysterious error.
+var handleFailure = function(o) {
+    if(o.responseText !== undefined) {
+        var div = document.getElementById('error');
+        div.innerHTML = 'An error has occurred';
+    }
+}
+
+// Map request returns to functions so the proper one will be called
+var callback = {
+    success:handleSuccess,
+    failure:handleFailure
+}
+
+// Sets up the request and sends it
+function makeRequest(inputdata) {
+    var rpcUrl = 'rpc.php';
+    var postData = 'inputdata=' + inputdata;
+    var request = YAHOO.util.Connect.asyncRequest('POST', rpcUrl, callback, postData);
+}
+
+// Once the DOM is ready, add event listeners
+YAHOO.util.Event.onDOMReady(addListeners);
Index: blocks/anonymous_grade/block_anonymous_grade.php
===================================================================
RCS file: blocks/anonymous_grade/block_anonymous_grade.php
diff -N blocks/anonymous_grade/block_anonymous_grade.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ blocks/anonymous_grade/block_anonymous_grade.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,39 @@
+<?php // $Id: block_anonymous_grade.php,v 2.5 2008/05/14 09:53:43 pcali1 Exp $   
+
+/**
+ * Author: Philip Cali
+ * This is a simple block that acts as an interface to enable extra grading features
+ * that LSU or other schools might find useful
+ */
+ 
+class block_anonymous_grade extends block_list {
+
+    function init() {
+        $this->title = get_string('blockname', 'block_anonymous_grade');
+        $this->version = 2008091711;
+    }
+
+    function get_content() {
+        global $CFG, $USER, $COURSE;
+
+        //if this user is not an admin, then this user won't be able to use the block
+        if (!is_siteadmin($USER->id)){
+            return;
+        }
+
+        if ($this->content !== NULL) {
+            return $this->content;
+        }
+
+        $this->content = new stdClass;
+        $this->content->footer = '';
+        $this->content->items = array();
+        $this->content->icons = array();
+    
+        $this->content->items[] = '<a href="'.$CFG->wwwroot.'/blocks/anonymous_grade/enable.php">'.
+                                  get_string('extra_features', 'block_anonymous_grade').'</a>';
+        return $this->content;
+    }
+}
+
+?>
Index: grade/report/simple_grader/index.php
===================================================================
RCS file: grade/report/simple_grader/index.php
diff -N grade/report/simple_grader/index.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ grade/report/simple_grader/index.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,255 @@
+<?php // $Id: index.php,v 1.65.2.9 2008-05-01 17:03:46 pcali1 Exp $
+
+///////////////////////////////////////////////////////////////////////////
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999 onwards  Martin Dougiamas  http://moodle.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+
+require_once '../../../config.php';
+require_once $CFG->dirroot.'/lib/gradelib.php';
+require_once $CFG->dirroot.'/grade/lib.php';
+require_once $CFG->dirroot.'/grade/report/simple_grader/lib.php';
+
+/**
+ * Edited by: Philip Cali (pcali1) and Robert Russo
+ * Date: 05/01/2008
+ */
+
+$courseid      = required_param('id');                   // course id
+$page          = optional_param('page', 0, PARAM_INT);   // active page
+$perpageurl    = optional_param('perpage', 0, PARAM_INT);
+$edit          = optional_param('edit', -1, PARAM_BOOL); // sticky editting mode
+
+$sortitemid    = optional_param('sortitemid', 0, PARAM_ALPHANUM); // sort by which grade item
+$action        = optional_param('action', 0, PARAM_ALPHAEXT);
+$move          = optional_param('move', 0, PARAM_INT);
+$type          = optional_param('type', 0, PARAM_ALPHA);
+$target        = optional_param('target', 0, PARAM_ALPHANUM);
+$toggle        = optional_param('toggle', NULL, PARAM_INT);
+$toggle_type   = optional_param('toggle_type', 0, PARAM_ALPHANUM);
+
+/// basic access checks
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('nocourseid');
+}
+require_login($course);
+$context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+require_capability('gradereport/simple_grader:view', $context);
+require_capability('moodle/grade:viewall', $context);
+
+require_js($CFG->wwwroot . '/grade/report/simple_grader/functions.js');
+
+/// return tracking object
+$gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'simple_grader', 'courseid'=>$courseid, 'page'=>$page));
+
+/// last selected report session tracking
+if (!isset($USER->grade_last_report)) {
+    $USER->grade_last_report = array();
+}
+$USER->grade_last_report[$course->id] = 'simple_grader';
+
+/// Build navigation
+
+$strgrades  = get_string('grades');
+$reportname = get_string('modulename', 'gradereport_simple_grader');
+
+$navigation = grade_build_nav(__FILE__, $reportname, $courseid);
+
+/// Build editing on/off buttons
+
+if (!isset($USER->gradeediting)) {
+    $USER->gradeediting = array();
+}
+
+if (has_capability('moodle/grade:edit', $context)) {
+    if (!isset($USER->gradeediting[$course->id])) {
+        $USER->gradeediting[$course->id] = 0;
+    }
+
+    if (($edit == 1) and confirm_sesskey()) {
+        $USER->gradeediting[$course->id] = 1;
+    } else if (($edit == 0) and confirm_sesskey()) {
+        $USER->gradeediting[$course->id] = 0;
+    }
+
+    // page params for the turn editting on
+    $options = $gpr->get_options();
+    $options['sesskey'] = sesskey();
+
+    if ($USER->gradeediting[$course->id]) {
+        $options['edit'] = 0;
+        $string = get_string('turneditingoff');
+    } else {
+        $options['edit'] = 1;
+        $string = get_string('turneditingon');
+    }
+
+    $buttons = print_single_button('index.php', $options, $string, 'get', '_self', true);
+
+} else {
+    $USER->gradeediting[$course->id] = 0;
+    $buttons = '';
+}
+
+$gradeserror = array();
+
+// Handle toggle change request
+if (!is_null($toggle) && !empty($toggle_type)) {
+    set_user_preferences(array('grade_report_simple_show'.$toggle_type => $toggle));
+}
+
+//first make sure we have proper final grades - this must be done before constructing of the grade tree
+simple_grade_regrade_final_grades($courseid);
+
+// Perform actions
+if (!empty($target) && !empty($action) && confirm_sesskey()) {
+    grade_report_simple_grader::process_action($target, $action);
+}
+
+// Initialise the grader report object
+$report = new grade_report_simple_grader($courseid, $gpr, $context, $page, $sortitemid);
+
+
+/// processing posted grades & feedback here
+if ($data = data_submitted() and confirm_sesskey() and has_capability('moodle/grade:edit', $context)) {
+    $warnings = $report->process_data($data);
+} else {
+    $warnings = array();
+}
+
+
+// Override perpage if set in URL
+if ($perpageurl) {
+    $report->user_prefs['studentsperpage'] = $perpageurl;
+}
+
+// final grades MUST be loaded after the processing
+$report->load_users();
+$numusers = $report->get_numusers();
+$report->load_final_grades();
+
+/// Print header
+print_header_simple($strgrades.': '.$reportname, ': '.$strgrades, $navigation,
+             '', '<!--[if IE]><link rel="stylesheet" type="text/css" href="styles_ie.css" />'. 
+             '<![endif]--><!--[if IE 6]><link rel="stylesheet" type="text/css" href="styles_ie6.css"'.
+             '/><![endif]-->', true, $buttons, navmenu($course));
+
+/// Print the plugin selector at the top
+print_grade_plugin_selector($courseid, 'report', 'simple_grader');
+
+// Add tabs
+$currenttab = 'simple_graderreport';
+require('tabs.php');
+
+echo $report->group_selector;
+echo '<div class="clearer"></div>';
+echo $report->get_toggles_html();
+
+//show warnings if any
+foreach($warnings as $warning) {
+    notify($warning);
+}
+
+$studentsperpage = $report->get_pref('simple_studentsperpage');
+// Don't use paging if studentsperpage is empty or 0 at course AND site levels
+if (!empty($studentsperpage)) {
+    custom_paging_bar($numusers, $report, $studentsperpage, $report);
+}
+
+// Does the user want to use the 'sticky' tabs feature
+$stickiness = $report->get_pref('simple_showstickytab');
+
+$reporthtml = '';
+// If the user wants the sticky preference, then we have to generate two tables
+// of information
+if ($stickiness === '1'){
+    $reporthtml .= '<div class="gradeparent"><div class="left_scroller">';
+    $reporthtml .= '<table id="fixes_column" class="fixed_grades_column"> <tbody class="lefftbody">';
+    $reporthtml .= $report->get_leftheaderhtml();
+    $reporthtml .= $report->get_lefticonshtml();
+    $reporthtml .= $report->get_leftrangehtml();
+    $reporthtml .= $report->get_leftstudentshtml();
+    $reporthtml .= $report->get_leftavghtml(true);
+    $reporthtml .= $report->get_leftavghtml();
+    $reporthtml .= "</tbody></table>";
+
+    $reporthtml .= "</div>";
+
+    $report->rowcount = 0;
+
+    $reporthtml .= '<div class="right_scroller"><table id="user-grades" class="gradestable flexible boxaligncenter generaltable"> <tbody class="righttest">';
+    $reporthtml .= $report->get_rightheaderhtml();
+    $reporthtml .= $report->get_righticonshtml();
+    $reporthtml .= $report->get_rightrangehtml();
+    $reporthtml .= $report->get_rightstudentshtml();
+    $reporthtml .= $report->get_rightavghtml(true);
+    $reporthtml .= $report->get_rightavghtml();
+    $reporthtml .= "</tbody></table></div></div>";
+} else {
+    // No sticky preference means, it's life as usual for the simple grader
+    $reporthtml .= '<table id="user-grades" class="gradestable flexible boxaligncenter generaltable fullgradestable">';
+    $reporthtml .= $report->get_headerhtml();
+    $reporthtml .= $report->get_iconshtml();
+    $reporthtml .= $report->get_rangehtml();
+    $reporthtml .= $report->get_studentshtml();
+    $reporthtml .= $report->get_avghtml(true);
+    $reporthtml .= $report->get_avghtml();
+    $reporthtml .= "</table>";
+    
+}
+
+// print submit button
+if ($USER->gradeediting[$course->id]) {
+    echo '<form action="index.php" method="post">';
+    echo '<div>';
+    echo '<input type="hidden" value="'.$courseid.'" name="id" />';
+    echo '<input type="hidden" value="'.sesskey().'" name="sesskey" />';
+    echo '<input type="hidden" value="grader" name="report"/>';
+}
+
+echo $reporthtml;
+
+// print submit button
+//Removed the check for quick editing, because it only confused teachers
+if ($USER->gradeediting[$course->id] || $report->get_pref('simple_showquickfeedback') /*|| $report->get_pref('simple_quickgrading'))*/) {
+    echo '<div class="submit"><input type="submit" value="'.get_string('update').'" /></div>';
+    echo '</div></form>';
+}
+
+// prints paging bar at bottom for large pages
+if (!empty($studentsperpage) && $studentsperpage >= 20) {
+    custom_paging_bar($numusers, $report, $studentsperpage, $report);
+}
+
+print_footer($course);
+
+function custom_paging_bar($numusers, $report, $studentsperpage, $report) {
+    $pager = print_paging_bar($numusers, $report->page, $studentsperpage, $report->pbarurl, 'page', false, true);
+    preg_match_all('/href="[^ ]*"/', $pager, $matches);
+    foreach ($matches[0] as $match) {
+        $href = substr($match, 6, -1);
+        $pager = str_replace($match, 'href="#" onclick="submitWarning(\''.$href.'\')"', $pager);
+    }
+    echo $pager;
+}
+
+?>

