]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-10231 merge grade_calculations and grade_items table + calculation improvements
authorskodak <skodak>
Sat, 23 Jun 2007 16:33:17 +0000 (16:33 +0000)
committerskodak <skodak>
Sat, 23 Jun 2007 16:33:17 +0000 (16:33 +0000)
MDL-10233 fixed grade_*::fetch() - does not modify $this anymore, we can now use it from normal methods to fetch other objects of the same class.

17 files changed:
backup/backuplib.php
backup/restorelib.php
lib/db/install.xml
lib/db/upgrade.php
lib/grade/grade_calculation.php [deleted file]
lib/grade/grade_category.php
lib/grade/grade_grades.php
lib/grade/grade_grades_text.php
lib/grade/grade_history.php
lib/grade/grade_item.php
lib/grade/grade_outcome.php
lib/grade/grade_scale.php
lib/gradelib.php
lib/simpletest/fixtures/gradetest.php
lib/simpletest/grade/simpletest/testgradecalculation.php [deleted file]
lib/simpletest/grade/simpletest/testgradeitem.php
version.php

index a3aac290a5b80cf57e6841f14a440a7485bfe794..885de7b36469db4f8b4a207779d1824c0a6932b2 100644 (file)
                 fwrite ($bf,full_tag("ITEMNUMBER",5,false,$grade_item->itemnumber));
                 fwrite ($bf,full_tag("ITEMINFO",5,false,$grade_item->iteminfo));
                 fwrite ($bf,full_tag("IDNUMBER",5,false,$grade_item->idnumber));
+                // use [idnumber] in calculation instead of [#giXXX#]
+                fwrite ($bf,full_tag("CALCULATION",5,false,$grade_item->get_caclulation()));
                 fwrite ($bf,full_tag("GRADEMAX",5,false,$grade_item->grademax));
                 fwrite ($bf,full_tag("GRADEMIN",5,false,$grade_item->grademin));
                 fwrite ($bf,full_tag("SCALEID",5,false,$grade_item->scaleid));
                 fwrite ($bf,full_tag("LOCKTIME",5,false,$grade_item->locktime));
 
                 // back up the other stuff here                
-                $status = backup_gradebook_calculations_info($bf,$preferences,$grade_item->id);              
                 $status = backup_gradebook_grades_info($bf,$preferences,$grade_item->id);
                 $status = backup_gradebook_grades_history_info($bf,$preferences,$grade_item->id);
                 $status = backup_gradebook_grades_text_info($bf,$preferences,$grade_item->id);
 
         return $status;
     }
-    //Backup gradebook_calculations(called from backup_gradebook_item_info
-    function backup_gradebook_calculations_info($bf,$preferences, $itemid) {
-
-        global $CFG;
-
-        $status = true;
-        
-        // find all calculations belonging to this item
-        if ($calculations = get_records('grade_calculations', 'itemid', $itemid)) {
-            fwrite ($bf,start_tag("GRADE_CALCULATIONS",5,true));
-            foreach ($calculations as $calculation) {
-                fwrite ($bf,start_tag("GRADE_CALCULATION",6,true));
-                fwrite ($bf,full_tag("ID",7,false,$calculation->id));
-                fwrite ($bf,full_tag("CALCULATION",7,false,$calculation->calculation));
-                fwrite ($bf,full_tag("USERMODIFIED",7,false,$calculation->usermodified));
-                fwrite ($bf,end_tag("GRADE_CALCULATION",6,true));
-            }  
-            $status = fwrite ($bf,end_tag("GRADE_CALCULATIONS",5,true));
-        }
-        return $status;
-    }
 
     function backup_gradebook_grades_info($bf,$preferences, $itemid) {
 
 
         $status = true;
         
-        // find all calculations belonging to this item
-        if ($raws = get_records('grade_grades', 'itemid', $itemid)) {
+        // find all grades belonging to this item
+        if ($grades = get_records('grade_grades', 'itemid', $itemid)) {
             fwrite ($bf,start_tag("GRADE_GRADES",5,true));
-            foreach ($raws as $raw) {
+            foreach ($grades as $grade) {
                 fwrite ($bf,start_tag("GRADE",6,true));
-                fwrite ($bf,full_tag("ID",7,false,$raw->id));
-                fwrite ($bf,full_tag("USERID",7,false,$raw->userid));
-                fwrite ($bf,full_tag("RAWGRADE",7,false,$raw->rawgrade));
-                fwrite ($bf,full_tag("RAWGRADEMAX",7,false,$raw->rawgrademax));
-                fwrite ($bf,full_tag("RAWGRADEMIN",7,false,$raw->rawgrademin));
-                fwrite ($bf,full_tag("RAWSCALEID",7,false,$raw->rawscaleid));
-                fwrite ($bf,full_tag("USERMODIFIED",7,false,$raw->usermodified));
-                fwrite ($bf,full_tag("FINALGRADE",7,false,$raw->finalgrade));
+                fwrite ($bf,full_tag("ID",7,false,$grade->id));
+                fwrite ($bf,full_tag("USERID",7,false,$grade->userid));
+                fwrite ($bf,full_tag("RAWGRADE",7,false,$grade->rawgrade));
+                fwrite ($bf,full_tag("RAWGRADEMAX",7,false,$grade->rawgrademax));
+                fwrite ($bf,full_tag("RAWGRADEMIN",7,false,$grade->rawgrademin));
+                fwrite ($bf,full_tag("RAWSCALEID",7,false,$grade->rawscaleid));
+                fwrite ($bf,full_tag("USERMODIFIED",7,false,$grade->usermodified));
+                fwrite ($bf,full_tag("FINALGRADE",7,false,$grade->finalgrade));
                 fwrite ($bf,full_tag("HIDDEN",7,false,$final->hidden));
                 fwrite ($bf,full_tag("LOCKED",7,false,$final->locked));
                 fwrite ($bf,full_tag("LOCKTIME",7,false,$final->locktime));
 
         $status = true;
         
-        // find all calculations belonging to this item
+        // find all grade texts belonging to this item
         if ($texts = get_records('grade_grades_text', 'itemid', $itemid)) {
             fwrite ($bf,start_tag("GRADE_GRADES_TEXT",5,true));
             foreach ($texts as $text) {
 
         $status = true;
         
-        // find all calculations belonging to this item
+        // find all grade history belonging to this item
         if ($histories = get_records('grade_history', 'itemid', $itemid)) {
             fwrite ($bf,start_tag("GRADE_GRADES_HISTORY",5,true));
             foreach ($histories as $history) {
index e3cb459aa5223034891d5b07b3405907d082e271..f9f5c439db001bc38d7ce913fb36f8adb45c7de0 100644 (file)
                             $dbrec->itemnumber = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#']);
                             $dbrec->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#']);
                             $dbrec->idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#']);
+                            $dbrec->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#']);
                             $dbrec->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#']);
                             $dbrec->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#']);
                             /// needs to be restored first
 
                             $itemid = insert_record('grade_items',$dbrec);
                             
-                            /// now, restore grade_calculations, grade_raw, grade_final, grade_text, and grade_history
+                            /// now, restore grade_grades, grade_text, and grade_history
                             if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']) && ($grades = $info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
                                 //Iterate over items
                                 for($i = 0; $i < sizeof($grades); $i++) {
                                 }
                             }
                                
-                            /// processing grade_calculations
-                            if (!empty($info['GRADE_ITEM']['#']['GRADE_CALCULATIONS']['0']['#']) && ($calcs = $info['GRADE_ITEM']['#']['GRADE_CALCULATIONS']['0']['#']['GRADE_CALCULATION'])) {
-                                //Iterate over items
-                                for($i = 0; $i < sizeof($calcs); $i++) {
-                                    $ite_info = $calcs[$i];
-                                    //traverse_xmlize($ite_info);
-//Debug
-                                    //print_object ($GLOBALS['traverse_array']);
-//Debug
-                                    //$GLOBALS['traverse_array']="";                                                              //Debug
-                                    $calc->itemid       = $itemid;
-
-                                    $calc->calculation = backup_todb($ite_info['#']['CALCULATION']['0']['#']);
-                                    
-                                    $modifier = backup_getid($restore->backup_unique_code,"user", backup_todb($ite_info['#']['USERMODIFIED']['0']['#']));
-                                    $calc->usermodified = $modifier->new_id;
-                                
-                                    insert_record('grade_calculations', $calc);
-                                    
-                                    $counter++;
-                                    if ($counter % 20 == 0) {
-                                        if (!defined('RESTORE_SILENTLY')) {
-                                            echo ".";
-                                            if ($counter % 400 == 0) {
-                                                echo "<br />";
-                                            }
-                                        }
-                                        backup_flush(300);
-                                    }
-                                }
-                            }
 
                             /// processing grade_grades_text
                             if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES_TEXT']['0']['#']) && ($texts = $info['GRADE_ITEM']['#']['GRADE_GRADES_TEXT']['0']['#']['GRADE_TEXT'])) {
index 841978717b219ab2d4376552f2d0a3e2aa44d452..9d2717c703a3326dab9015c93c028d51aba452aa 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20070619" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20070623" COMMENT="XMLDB file for core Moodle tables"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
 >
         <FIELD NAME="iteminstance" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="id of the item module" PREVIOUS="itemmodule" NEXT="itemnumber"/>
         <FIELD NAME="itemnumber" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="Can be used to distinguish multiple grades for an activity" PREVIOUS="iteminstance" NEXT="iteminfo"/>
         <FIELD NAME="iteminfo" TYPE="text" LENGTH="medium" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="Info and notes about this item XXX" PREVIOUS="itemnumber" NEXT="idnumber"/>
-        <FIELD NAME="idnumber" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="Arbitrary idnumber provided by the module responsible" PREVIOUS="iteminfo" NEXT="gradetype"/>
-        <FIELD NAME="gradetype" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" ENUM="false" COMMENT="0 = none, 1 = value, 2 = scale, 3 = text" PREVIOUS="idnumber" NEXT="grademax"/>
+        <FIELD NAME="idnumber" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="Arbitrary idnumber provided by the module responsible" PREVIOUS="iteminfo" NEXT="calculation"/>
+        <FIELD NAME="calculation" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="Formula describing how to derive this grade from other items, referring to them using giXXX where XXX is grade item id ... eg something like: =sin(square([#gi20#])) + [#gi30#]" PREVIOUS="idnumber" NEXT="gradetype"/>
+        <FIELD NAME="gradetype" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" ENUM="false" COMMENT="0 = none, 1 = value, 2 = scale, 3 = text" PREVIOUS="calculation" NEXT="grademax"/>
         <FIELD NAME="grademax" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="100" SEQUENCE="false" ENUM="false" DECIMALS="5" COMMENT="What is the maximum allowable grade?" PREVIOUS="gradetype" NEXT="grademin"/>
         <FIELD NAME="grademin" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" DECIMALS="5" COMMENT="What is the minimum allowable grade?" PREVIOUS="grademax" NEXT="scaleid"/>
         <FIELD NAME="scaleid" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="If this grade is based on a scale, which one is it?" PREVIOUS="grademin" NEXT="outcomeid"/>
         <KEY NAME="outcomeid" TYPE="foreign" FIELDS="outcomeid" REFTABLE="grade_outcomes" REFFIELDS="id" PREVIOUS="scaleid"/>
       </KEYS>
     </TABLE>
-    <TABLE NAME="grade_categories" COMMENT="This table keeps information about categories, used for grouping items." PREVIOUS="grade_items" NEXT="grade_calculations">
+    <TABLE NAME="grade_categories" COMMENT="This table keeps information about categories, used for grouping items." PREVIOUS="grade_items" NEXT="grade_grades">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="true" ENUM="false" COMMENT="id of the table, please edit me" NEXT="courseid"/>
         <FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="The course this grade category is part of" PREVIOUS="id" NEXT="parent"/>
         <KEY NAME="parent" TYPE="foreign" FIELDS="parent" REFTABLE="grade_categories" REFFIELDS="id" PREVIOUS="courseid"/>
       </KEYS>
     </TABLE>
-    <TABLE NAME="grade_calculations" COMMENT="This table describes the calculated grade_items in more details." PREVIOUS="grade_categories" NEXT="grade_grades">
-      <FIELDS>
-        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="true" ENUM="false" COMMENT="id of the table, please edit me" NEXT="itemid"/>
-        <FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="The grade_item this relates to" PREVIOUS="id" NEXT="calculation"/>
-        <FIELD NAME="calculation" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="Formula describing how to derive this grade from other items, referring to them using [idnumber] ... eg something like:sin(square([XXXXX])) + [YYYY]" PREVIOUS="itemid" NEXT="timecreated"/>
-        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the time this calculation was first created" PREVIOUS="calculation" NEXT="timemodified"/>
-        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the time this calculation was last modified" PREVIOUS="timecreated" NEXT="usermodified"/>
-        <FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the userid of the person who last modified this calculation" PREVIOUS="timemodified"/>
-      </FIELDS>
-      <KEYS>
-        <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="primary key of the table, please edit me" NEXT="itemid"/>
-        <KEY NAME="itemid" TYPE="foreign" FIELDS="itemid" REFTABLE="grade_items" REFFIELDS="id" PREVIOUS="primary" NEXT="usermodified"/>
-        <KEY NAME="usermodified" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id" PREVIOUS="itemid"/>
-      </KEYS>
-    </TABLE>
-    <TABLE NAME="grade_grades" COMMENT="grade_grades  This table keeps individual grades for each user and each item, exactly as imported or submitted by modules. The rawgrademax/min and rawscaleid are stored here to record the values at the time the grade was stored, because teachers might change this for an activity! All the results are normalised/resampled for the final grade value." PREVIOUS="grade_calculations" NEXT="grade_grades_text">
+    <TABLE NAME="grade_grades" COMMENT="grade_grades  This table keeps individual grades for each user and each item, exactly as imported or submitted by modules. The rawgrademax/min and rawscaleid are stored here to record the values at the time the grade was stored, because teachers might change this for an activity! All the results are normalised/resampled for the final grade value." PREVIOUS="grade_categories" NEXT="grade_grades_text">
       <FIELDS>
         <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="true" ENUM="false" COMMENT="id of the table, please edit me" NEXT="itemid"/>
         <FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="The item this grade belongs to" PREVIOUS="id" NEXT="userid"/>
index 7e63cf4844a972d3699832158c168b857f5004e6..694bb843a96214279d192eef99cbd9ae0356eaf6 100644 (file)
@@ -819,6 +819,7 @@ function xmldb_main_upgrade($oldversion=0) {
         $table->addFieldInfo('itemnumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
         $table->addFieldInfo('iteminfo', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL, null, null, null, null);
         $table->addFieldInfo('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null);
+        $table->addFieldInfo('calculation', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null);
         $table->addFieldInfo('gradetype', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null, null, '0');
         $table->addFieldInfo('grademax', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, null, null, '100');
         $table->addFieldInfo('grademin', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, null, null, '0');
@@ -865,25 +866,6 @@ function xmldb_main_upgrade($oldversion=0) {
     /// Launch create table for grade_categories
         $result = $result && create_table($table);
         
-    /// Define table grade_calculations to be created
-        $table = new XMLDBTable('grade_calculations');
-
-    /// Adding fields to table grade_calculations
-        $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
-        $table->addFieldInfo('itemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
-        $table->addFieldInfo('calculation', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null);
-        $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
-        $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
-        $table->addFieldInfo('usermodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
-
-    /// Adding keys to table grade_calculations
-        $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
-        $table->addKeyInfo('itemid', XMLDB_KEY_FOREIGN, array('itemid'), 'grade_items', array('id'));
-        $table->addKeyInfo('usermodified', XMLDB_KEY_FOREIGN, array('usermodified'), 'user', array('id'));
-
-    /// Launch create table for grade_calculations
-        $result = $result && create_table($table);
-        
 
     /// Define table grade_grades to be created
         $table = new XMLDBTable('grade_grades');
@@ -1006,17 +988,6 @@ function xmldb_main_upgrade($oldversion=0) {
         $result = $result && add_field($table, $field);
     }
 
-    if ($result && $oldversion < 2007042601) {
-
-    /// Changing nullability of field usermodified on table grade_calculations to null
-        $table = new XMLDBTable('grade_calculations');
-        $field = new XMLDBField('usermodified');
-        $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null, 'timemodified');
-
-        /// Launch change of nullability for field usermodified
-        $result = $result && change_field_notnull($table, $field);
-    }    
-    
     if ($result && $oldversion < 2007042701) {
 
     /// Define key categoryid (foreign) to be dropped form grade_categories
@@ -1288,25 +1259,6 @@ function xmldb_main_upgrade($oldversion=0) {
             $result = $result && create_table($table);
         }
 
-        /// Remove the obsoleted unitttests tables - they will be recreated automatically
-        $tables = array('grade_categories',
-                        'scale',
-                        'grade_items',
-                        'grade_calculations',
-                        'grade_grades_raw',
-                        'grade_grades_final',
-                        'grade_grades_text',
-                        'grade_outcomes',
-                        'grade_history');
-
-        foreach ($tables as $table) {
-            $table = new XMLDBTable('unittest_'.$table);
-            if (table_exists($table)) {
-                drop_table($table);
-            }
-
-        }
-
     /// Define table grade_import_values to be created
         $table = new XMLDBTable('grade_import_values');
         if (table_exists($table)) {
@@ -1362,6 +1314,46 @@ function xmldb_main_upgrade($oldversion=0) {
         }
     }
 
+
+/// merge calculation formula into grade_item
+    if ($result && $oldversion < 2007062301) {
+
+    /// Delete obsoleted calculations table - we did not need the data yet
+        $table = new XMLDBTable('grade_calculations');
+        if (table_exists($table)) {
+            drop_table($table);
+        }
+
+    /// Define field calculation to be added to grade_items
+        $table = new XMLDBTable('grade_items');
+        $field = new XMLDBField('calculation');
+
+        if (!field_exists($table, $field)) {
+            $field->setAttributes(XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null, 'idnumber');
+        /// Launch add field calculation
+            $result = $result && add_field($table, $field);
+        }
+
+        /// Remove the obsoleted unitttests tables - they will be recreated automatically
+        $tables = array('grade_categories',
+                        'scale',
+                        'grade_items',
+                        'grade_calculations',
+                        'grade_grades_raw',
+                        'grade_grades_final',
+                        'grade_grades_text',
+                        'grade_outcomes',
+                        'grade_history');
+
+        foreach ($tables as $table) {
+            $table = new XMLDBTable('unittest_'.$table);
+            if (table_exists($table)) {
+                drop_table($table);
+            }
+        }
+
+    }
+
     return $result;
 }
 
diff --git a/lib/grade/grade_calculation.php b/lib/grade/grade_calculation.php
deleted file mode 100644 (file)
index c0c7a7a..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-<?php // $Id$
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// NOTICE OF COPYRIGHT                                                   //
-//                                                                       //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//          http://moodle.com                                            //
-//                                                                       //
-// Copyright (C) 2001-2007  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                         //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-require_once('grade_object.php');
-
-/**
- * A calculation string used to compute the value displayed by a grade_item.
- * There can be only one grade_calculation per grade_item (one-to-one).
- *
- * Calculation formula may use final grades of other grade items (giXXX
- * where XXX is the id number of grade item). The result is stored in
- * finalgrade field. The rawgrade is not used at all.
- */
-class grade_calculation extends grade_object {
-    /**
-     * DB Table (used by grade_object).
-     * @var string $table
-     */
-    var $table = 'grade_calculations';
-
-    /**
-     * Array of class variables that are not part of the DB table fields
-     * @var array $nonfields
-     */
-    var $nonfields = array('table', 'nonfields', 'formula', 'grade_item');
-
-    /**
-     * A reference to the grade_item this calculation belongs to.
-     * @var int $itemid
-     */
-    var $itemid;
-
-    /**
-     * The string representation of the calculation.
-     * @var string $calculation
-     */
-    var $calculation;
-
-    /**
-     * The userid of the person who last modified this calculation.
-     * @var int $usermodified
-     */
-    var $usermodified;
-
-    /**
-     * Grade item object
-     */
-    var $grade_item;
-
-    /**
-     * Math evaluation object
-     */
-    var $formula;
-
-    /**
-     * Loads the grade_item object referenced by $this->itemid and saves it as $this->grade_item for easy access.
-     * @return object grade_item.
-     */
-    function load_grade_item() {
-        if (empty($this->grade_item) && !empty($this->itemid)) {
-            $this->grade_item = grade_item::fetch('id', $this->itemid);
-        }
-        return $this->grade_item;
-    }
-
-    /**
-     * Applies the formula represented by this object. The parameteres are taken from final
-     * grades of grade items in current course only.
-     * @return boolean false if error
-     */
-    function compute() {
-        global $CFG;
-        require_once($CFG->libdir.'/mathslib.php');
-
-        if (empty($this->id) or empty($this->itemid)) {
-            debugging('Can not initialize calculation!');
-            return false;
-        }
-
-        // init grade_item
-        $this->load_grade_item();
-
-        if ($this->grade_item->is_locked()) {
-            return true; // no need to recalculate locked items
-        }
-
-        //get used items
-        $useditems = $this->dependson();
-
-        // init maths library
-        $this->formula = new calc_formula($this->calculation);
-
-        // where to look for final grades?
-        // this itemid is added so that we use only one query for source and final grades
-        $gis = implode(',', array_merge($useditems, array($this->itemid)));
-
-        $sql = "SELECT g.*
-                  FROM {$CFG->prefix}grade_grades g, {$CFG->prefix}grade_items gi
-                 WHERE gi.id = g.itemid AND gi.courseid={$this->grade_item->courseid} AND gi.id IN ($gis)
-              ORDER BY g.userid";
-
-        $return = true;
-
-        // group the grades by userid and use formula on the group
-        if ($rs = get_recordset_sql($sql)) {
-            if ($rs->RecordCount() > 0) {
-                $prevuser = 0;
-                $grades   = array();
-                $final    = null;
-                while ($used = rs_fetch_next_record($rs)) {
-                    if ($used->userid != $prevuser) {
-                        if (!$this->use_formula($prevuser, $grades, $useditems, $final)) {
-                            $return = false;
-                        }
-                        $prevuser = $used->userid;
-                        $grades   = array();
-                        $final    = null;
-                    }
-                    if ($used->itemid == $this->grade_item->id) {
-                        $final = new grade_grades($used, false); // fetching from db is not needed
-                        $final->grade_item =& $this->grade_item;
-                    }
-                    $grades['gi'.$used->itemid] = $used->finalgrade;
-                }
-                if (!$this->use_formula($prevuser, $grades, $useditems, $final)) {
-                    $return = false;
-                }
-            }
-        }
-
-        //TODO: we could return array of errors here
-        return $return;
-    }
-
-    /**
-     * internal function - does the final grade calculation
-     */
-    function use_formula($userid, $params, $useditems, $final) {
-        if (empty($userid)) {
-            return true;
-        }
-
-        // add missing final grade values
-        // not graded (null) is counted as 0 - the spreadsheet way
-        foreach($useditems as $gi) {
-            if (!array_key_exists('gi'.$gi, $params)) {
-                $params['gi'.$gi] = 0;
-            } else {
-                $params['gi'.$gi] = (float)$params['gi'.$gi];
-            }
-        }
-
-        // can not use own final grade during calculation
-        unset($params['gi'.$this->grade_item->id]);
-
-        // insert final grade - will be needed later anyway
-        if (empty($final)) {
-            $final = new grade_grades(array('itemid'=>$this->grade_item->id, 'userid'=>$userid), false);
-            $final->insert();
-            $final->grade_item =& $this->grade_item;
-
-        } else if ($final->is_locked()) {
-            // no need to recalculate locked grades
-            return;
-        }
-
-
-        // do the calculation
-        $this->formula->set_params($params);
-        $result = $this->formula->evaluate();
-
-        // store the result
-        if ($result === false) {
-            // error during calculation
-            if (!is_null($final->finalgrade) or !is_null($final->rawgrade)) {
-                $final->finalgrade = null;
-                $final->rawgrade   = null;
-                $final->update();
-            }
-            return false;
-
-        } else {
-            // normalize
-            $result = bounded_number($this->grade_item->grademin, $result, $this->grade_item->grademax);
-            if ($this->grade_item->gradetype == GRADE_TYPE_SCALE) {
-                $result = round($result+0.00001); // round scales upwards
-            }
-
-            // store only if final grade changed, remove raw grade because we do not need it
-            if ($final->finalgrade != $result or !is_null($final->rawgrade)) {
-                $final->finalgrade = $result;
-                $final->rawgrade   = null;
-                $final->update();
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Finds out on which other items does this calculation depend
-     * @return array of grade_item ids this one depends on
-     */
-    function dependson() {
-        if (preg_match_all('/gi([0-9]+)/i', $this->calculation, $matches)) {
-            return ($matches[1]);
-        } else {
-            return array();
-        }
-    }
-
-    /**
-     * Finds and returns a grade_calculation object based on 1-3 field values.
-     *
-     * @param boolean $static Unless set to true, this method will also set $this object with the returned values.
-     * @param string $field1
-     * @param string $value1
-     * @param string $field2
-     * @param string $value2
-     * @param string $field3
-     * @param string $value3
-     * @param string $fields
-     * @return object grade_calculation object or false if none found.
-     */
-    function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
-        if ($grade_calculation = get_record('grade_calculations', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_calculation') {
-                print_object($this);
-                foreach ($grade_calculation as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_calculation = new grade_calculation($grade_calculation);
-                return $grade_calculation;
-            }
-        } else {
-            return false;
-        }
-    }
-}
-?>
index f5f7e82f6f21d3f033b823319422d06d17f2b133..07d0718f8264f2570601e51b0c2eb1db06ca3ab7 100644 (file)
@@ -153,6 +153,7 @@ class grade_category extends grade_object {
 
     /**
      * Finds and returns a grade_category object based on 1-3 field values.
+     * @static
      *
      * @param string $field1
      * @param string $value1
@@ -165,15 +166,9 @@ class grade_category extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
         if ($grade_category = get_record('grade_categories', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_category') {
-                foreach ($grade_category as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_category = new grade_category($grade_category);
-                return $grade_category;
-            }
+            $grade_category = new grade_category($grade_category);
+            return $grade_category;
+
         } else {
             return false;
         }
@@ -361,15 +356,15 @@ class grade_category extends grade_object {
 
 
         // find grde items of immediate children (category or grade items)
-        $dependson = $this->grade_item->dependson();
+        $depends_on = $this->grade_item->depends_on();
         $items = array();
 
-        foreach($dependson as $dep) {
+        foreach($depends_on as $dep) {
             $items[$dep] = grade_item::fetch('id', $dep);
         }
 
         // where to look for final grades - include or grade item too
-        $gis = implode(',', array_merge($dependson, array($this->grade_item->id)));
+        $gis = implode(',', array_merge($depends_on, array($this->grade_item->id)));
 
         $sql = "SELECT g.*
                   FROM {$CFG->prefix}grade_grades g, {$CFG->prefix}grade_items gi
@@ -384,7 +379,7 @@ class grade_category extends grade_object {
                 $final    = null;
                 while ($used = rs_fetch_next_record($rs)) {
                     if ($used->userid != $prevuser) {
-                        $this->aggregate_grades($prevuser, $items, $grades, $dependson, $final);
+                        $this->aggregate_grades($prevuser, $items, $grades, $depends_on, $final);
                         $prevuser = $used->userid;
                         $grades   = array();
                         $final    = null;
@@ -395,7 +390,7 @@ class grade_category extends grade_object {
                     }
                     $grades[$used->itemid] = $used->finalgrade;
                 }
-                $this->aggregate_grades($prevuser, $items, $grades, $dependson, $final);
+                $this->aggregate_grades($prevuser, $items, $grades, $depends_on, $final);
             }
         }
 
@@ -405,7 +400,7 @@ class grade_category extends grade_object {
     /**
      * internal function for category grades aggregation
      */
-    function aggregate_grades($userid, $items, $grades, $dependson, $final) {
+    function aggregate_grades($userid, $items, $grades, $depends_on, $final) {
         if (empty($userid)) {
             //ignore first run
             return;
@@ -480,7 +475,7 @@ class grade_category extends grade_object {
                 break;
 
             case GRADE_AGGREGATE_MEAN_ALL:    // Arithmetic average of all grade items including even NULLs; NULL grade caunted as minimum
-                $num = count($dependson);     // you can calculate sum from this one if you multiply it with count($this->dependson() ;-)
+                $num = count($depends_on);     // you can calculate sum from this one if you multiply it with count($this->depends_on() ;-)
                 $sum = array_sum($grades);
                 $rawgrade = $sum / $num;
                 break;
index 4362df57ec05c34cd643bf2d0293da8145a37a3f..7d05b5d5a4bce2f3a40b2eede22c9cf0e4042a49 100644 (file)
@@ -216,6 +216,7 @@ class grade_grades extends grade_object {
     /**
      * Finds and returns a grade_grades object based on 1-3 field values.
      * @static
+     *
      * @param string $field1
      * @param string $value1
      * @param string $field2
@@ -227,16 +228,9 @@ class grade_grades extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
         if ($object = get_record('grade_grades', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_grades') {
-                foreach ($object as $param => $value) {
-                    $this->$param = $value;
-                }
+            $object = new grade_grades($object);
+            return $object;
 
-                return $this;
-            } else {
-                $object = new grade_grades($object);
-                return $object;
-            }
         } else {
             return false;
         }
index ca88398b7f39b62d6bea71b9be4240e05e315553..3700232ffe3d5d68deaec4e6e574a8456cca7184 100644 (file)
@@ -92,6 +92,7 @@ class grade_grades_text extends grade_object {
 
     /**
      * Finds and returns a grade_text object based on 1-3 field values.
+     * @static
      *
      * @param boolean $static Unless set to true, this method will also set $this object with the returned values.
      * @param string $field1
@@ -105,15 +106,9 @@ class grade_grades_text extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
         if ($grade_text = get_record('grade_grades_text', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_grades_text') {
-                foreach ($grade_text as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_text = new grade_grades_text($grade_text);
-                return $grade_text;
-            }
+            $grade_text = new grade_grades_text($grade_text);
+            return $grade_text;
+
         } else {
             return false;
         }
index bb5400da1b20ed12004e6adb26cdd93f659336d1..9c8da938af5bef5ca3390a23da28b9b791d3e66b 100644 (file)
@@ -80,6 +80,7 @@ class grade_history extends grade_object {
 
     /**
      * Finds and returns a grade_history object based on 1-3 field values.
+     * @static
      *
      * @param string $field1
      * @param string $value1
@@ -92,15 +93,9 @@ class grade_history extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
         if ($grade_history = get_record('grade_history', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_history') {
-                foreach ($grade_history as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_history = new grade_history($grade_history);
-                return $grade_history;
-            }
+            $grade_history = new grade_history($grade_history);
+            return $grade_history;
+
         } else {
             return false;
         }
index 141213980c173e417656059d7ba9b8849bf28bc8..7b26cd560a6f2d1b88449e652a01a5abe175dcef 100644 (file)
@@ -40,7 +40,7 @@ class grade_item extends grade_object {
      * Array of class variables that are not part of the DB table fields
      * @var array $nonfields
      */
-    var $nonfields = array('table', 'nonfields', 'calculation', 'scale', 'category', 'outcome');
+    var $nonfields = array('table', 'nonfields', 'formula', 'calculation_normalized', 'scale', 'category', 'outcome');
 
     /**
      * The course this grade_item belongs to.
@@ -108,6 +108,23 @@ class grade_item extends grade_object {
      */
     var $idnumber;
 
+    /**
+     * Calculation string used for this item.
+     * @var string $calculation
+     */
+    var $calculation;
+
+    /**
+     * Indicates if we already tried to normalize the grade calculation formula.
+     * This flag helps to minimize db access when broken formulas used in calculation.
+     * @var boolean
+     */
+    var $calculation_normalized;
+    /**
+     * Math evaluation object
+     */
+    var $formula;
+
     /**
      * The type of grade (0 = none, 1 = value, 2 = scale, 3 = text)
      * @var int $gradetype
@@ -198,12 +215,6 @@ class grade_item extends grade_object {
      */
     var $needsupdate;
 
-    /**
-     * Calculation string used for this item.
-     * @var string $calculation
-     */
-    var $calculation;
-
     /**
      * Constructor. Extends the basic functionality defined in grade_object.
      * @param array $params Can also be a standard object.
@@ -263,6 +274,7 @@ class grade_item extends grade_object {
 
         $db_item = new grade_item(array('id' => $this->id));
 
+        $calculationdiff = $db_item->calculation != $this->calculation;
         $gradetypediff   = $db_item->gradetype   != $this->gradetype;
         $grademaxdiff    = $db_item->grademax    != $this->grademax;
         $grademindiff    = $db_item->grademin    != $this->grademin;
@@ -275,12 +287,14 @@ class grade_item extends grade_object {
         $needsupdatediff = !$db_item->needsupdate &&  $this->needsupdate;    // force regrading only if setting the flag first time
         $lockeddiff      = !empty($db_item->locked) && empty($this->locked); // force regrading only when unlocking
 
-        return ($gradetypediff || $grademaxdiff || $grademindiff || $scaleiddiff || $outcomeiddiff ||
-                $multfactordiff || $plusfactordiff || $deleteddiff || $needsupdatediff || $lockeddiff);
+        return ($calculationdiff || $gradetypediff || $grademaxdiff || $grademindiff || $scaleiddiff
+             || $outcomeiddiff || $multfactordiff || $plusfactordiff || $deleteddiff || $needsupdatediff
+             || $lockeddiff);
     }
 
     /**
      * Finds and returns a grade_item object based on 1-3 field values.
+     * @static
      *
      * @param string $field1
      * @param string $value1
@@ -293,16 +307,9 @@ class grade_item extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") {
         if ($grade_item = get_record('grade_items', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_item') {
-                foreach ($grade_item as $param => $value) {
-                    $this->$param = $value;
-                }
+            $grade_item = new grade_item($grade_item);
+            return $grade_item;
 
-                return $this;
-            } else {
-                $grade_item = new grade_item($grade_item);
-                return $grade_item;
-            }
         } else {
             return false;
         }
@@ -410,11 +417,11 @@ class grade_item extends grade_object {
      * @return boolean Locked state
      */
     function is_locked($userid=NULL) {
-         if (!empty($this->locked)) {
+        if (!empty($this->locked)) {
             return true;
-         }
+        }
 
-         if (!empty($userid)) {
+        if (!empty($userid)) {
 
             $grade = new grade_grades(array('itemid'=>$this->id, 'userid'=>$userid));
             $grade->grade_item =& $this; // prevent db fetching of cached grade_item
@@ -527,7 +534,7 @@ class grade_item extends grade_object {
         }
 
         if ($this->is_calculated()) {
-            if ($this->calculation->compute()) {
+            if ($this->compute()) {
                 $this->needsupdate = false;
                 $this->update();
                 return true;
@@ -775,14 +782,32 @@ class grade_item extends grade_object {
 
     /**
      * Checks if grade calculated. Returns this object's calculation.
-     * @return mixed $calculation Calculation object if exists, false otherwise.
+     * @return boolean true if grade item calculated.
      */
     function is_calculated() {
-        if (is_null($this->calculation)) {
-            $this->calculation = grade_calculation::fetch('itemid', $this->id);
+        if (empty($this->calculation)) {
+            return false;
+        }
+
+        /*
+         * The main reason why we use the [#gixxx#] instead of [idnumber] is speed of depends_on(),
+         * we would have to fetch all course grade items to find out the ids.
+         * Also if user changes the idnumber the formula does not need to be updated.
+         */
+
+        // first detect if we need to update calculation formula from [idnumber] to [#giXXX#] (after backup, etc.)
+        if (!$this->calculation_normalized and preg_match_all('/\[(?!#gi)(.*?)\]/', $this->calculation, $matches)) {
+            foreach ($matches[1] as $idnumber) {
+                if ($grade_item = grade_item::fetch('courseid', $this->courseid, 'idnumber', $idnumber)) {
+                    $this->calculation = str_replace('['.$grade_item->idnumber.']', '[#gi'.$grade_item->id.'#]', $this->calculation);
+                }
+            }
+            $this->update(); // update in db if needed
+            $this->calculation_normalized = true;
+            return !empty($this->calculation);
         }
 
-        return !empty($this->calculation);
+        return true;
     }
 
     /**
@@ -791,7 +816,20 @@ class grade_item extends grade_object {
      */
     function get_calculation() {
         if ($this->is_calculated()) {
-            return $this->calculation->calculation;
+            $formula = $this->calculation;
+            // denormalize formula - convert [#giXX#] to [idnumber]
+            if (preg_match_all('/\[#gi([0-9]+)#\]/', $formula, $matches)) {
+                foreach ($matches[1] as $id) {
+                    if ($grade_item = grade_item::fetch('id', $id)) {
+                        if (!empty($grade_item->idnumber)) {
+                            $formula = str_replace('[#gi'.$grade_item->id.'#]', '['.$grade_item->idnumber.']', $formula);
+                        }
+                    }
+                }
+            }
+
+            return $formula;
+
         } else {
             return NULL;
         }
@@ -805,40 +843,29 @@ class grade_item extends grade_object {
      * @return boolean success
      */
     function set_calculation($formula) {
-        // refresh cached calculation object
-        $this->calculation = null;
+        $formula = trim($formula);
 
-        $result = true;
+        if (empty($formula)) {
+            $this->calculation = NULL;
 
-        if (empty($formula)) { // We are removing this calculation
-            if (!empty($this->id) and $this->is_calculated()) {
-                $this->calculation->delete();
-                $this->calculation = null; // remove cache
+        } else {
+            if (strpos($formula, '=') !== 0) {
+                $formula = '='.$formula;
             }
 
-        } else { // We are updating or creating the calculation entry in the DB
-            if ($this->is_calculated()) {
-                $this->calculation->calculation = $formula;
-                if (!$this->calculation->update()) {
-                    $this->calculation = null; // remove cache
-                    $result = false;
-                    debugging("Could not save the calculation in the database for this grade_item.");
+            // normalize formula - we want grade item ids [#giXXX#] instead of [idnumber]
+            $grade_item = new grade_item(array('courseid'=>$this->courseid), false);
+            if ($grade_items = $grade_item->fetch_all_using_this()) {
+                foreach ($grade_items as $grade_item) {
+                    $formula = str_replace('['.$grade_item->idnumber.']', '[#gi'.$grade_item->id.'#]', $formula);
                 }
-
-            } else {
-                $grade_calculation = new grade_calculation(array('calculation'=>$formula, 'itemid'=>$this->id), false);
-                if (!$grade_calculation->insert()) {
-                    $this->calculation = null; // remove cache
-                    $result = false;
-                    debugging("Could not save the calculation in the database for this grade_item.");
-                }
-                $this->calculation = $grade_calculation;
             }
-        }
 
-        $this->force_regrading();
+            $this->calculation = $formula;
+        }
 
-        return $result;
+        $this->calculation_normalized = true;
+        return $this->update();
     }
 
     /**
@@ -959,18 +986,21 @@ class grade_item extends grade_object {
      * Finds out on which other items does this depend directly when doing calculation or category agregation
      * @return array of grade_item ids this one depends on
      */
-    function dependson() {
+    function depends_on() {
 
         if ($this->is_locked()) {
             // locked items do not need to be regraded
             return array();
         }
 
-        if ($calculation = $this->is_calculated()) {
-            return $calculation->dependson();
+        if ($this->is_calculated()) {
+            if (preg_match_all('/\[#gi([0-9]+)#\]/', $this->calculation, $matches)) {
+                return array_unique($matches[1]); // remove duplicates
+            } else {
+                return array();
+            }
 
-        } else if ($this->itemtype == 'category') {
-            $grade_category = grade_category::fetch('id', $this->iteminstance);
+        } else if ($grade_category = $this->load_category()) {
             $children = $grade_category->get_children(1, 'flat');
 
             if (empty($children)) {
@@ -979,15 +1009,13 @@ class grade_item extends grade_object {
 
             $result = array();
 
-            $childrentype = get_class(reset($children));
-            if ($childrentype == 'grade_category') {
-                foreach ($children as $id => $category) {
-                    $grade_item = $category->get_grade_item();
-                    $result[] = $grade_item->id;
-                }
-            } elseif ($childrentype == 'grade_item') {
-                foreach ($children as $id => $grade_item) {
+            foreach ($children as $id => $child) {
+                if (get_class($child) == 'grade_category') {
+                    $grade_item = $child->get_grade_item();
                     $result[] = $grade_item->id;
+
+                } else if (get_class($child) == 'grade_item') {
+                    $result[] = $child->id;
                 }
             }
 
@@ -1086,5 +1114,137 @@ class grade_item extends grade_object {
             return false;
         }
     }
+
+    /**
+     * Calculates final grade values useing the formula in calculation property.
+     * The parameteres are taken from final grades of grade items in current course only.
+     * @return boolean false if error
+     */
+    function compute() {
+        global $CFG;
+
+        if (!$this->is_calculated()) {
+            return false;
+        }
+
+        require_once($CFG->libdir.'/mathslib.php');
+
+        if ($this->is_locked()) {
+            return true; // no need to recalculate locked items
+        }
+
+        // get used items
+        $useditems = $this->depends_on();
+
+        // prepare formula and init maths library
+        $formula = preg_replace('/\[#(gi[0-9]+)#\]/', '\1', $this->calculation);
+        $this->formula = new calc_formula($formula);
+
+        // where to look for final grades?
+        // this itemid is added so that we use only one query for source and final grades
+        $gis = implode(',', array_merge($useditems, array($this->id)));
+
+        $sql = "SELECT g.*
+                  FROM {$CFG->prefix}grade_grades g, {$CFG->prefix}grade_items gi
+                 WHERE gi.id = g.itemid AND gi.courseid={$this->courseid} AND gi.id IN ($gis)
+              ORDER BY g.userid";
+
+        $return = true;
+
+        // group the grades by userid and use formula on the group
+        if ($rs = get_recordset_sql($sql)) {
+            if ($rs->RecordCount() > 0) {
+                $prevuser = 0;
+                $grades   = array();
+                $final    = null;
+                while ($used = rs_fetch_next_record($rs)) {
+                    if ($used->userid != $prevuser) {
+                        if (!$this->use_formula($prevuser, $grades, $useditems, $final)) {
+                            $return = false;
+                        }
+                        $prevuser = $used->userid;
+                        $grades   = array();
+                        $final    = null;
+                    }
+                    if ($used->itemid == $this->id) {
+                        $final = new grade_grades($used, false); // fetching from db is not needed
+                        $final->grade_item =& $this;
+                    }
+                    $grades['gi'.$used->itemid] = $used->finalgrade;
+                }
+                if (!$this->use_formula($prevuser, $grades, $useditems, $final)) {
+                    $return = false;
+                }
+            }
+        }
+
+        //TODO: we could return array of errors here
+        return $return;
+    }
+
+    /**
+     * internal function - does the final grade calculation
+     */
+    function use_formula($userid, $params, $useditems, $final) {
+        if (empty($userid)) {
+            return true;
+        }
+
+        // add missing final grade values
+        // not graded (null) is counted as 0 - the spreadsheet way
+        foreach($useditems as $gi) {
+            if (!array_key_exists('gi'.$gi, $params)) {
+                $params['gi'.$gi] = 0;
+            } else {
+                $params['gi'.$gi] = (float)$params['gi'.$gi];
+            }
+        }
+
+        // can not use own final grade during calculation
+        unset($params['gi'.$this->id]);
+
+        // insert final grade - will be needed later anyway
+        if (empty($final)) {
+            $final = new grade_grades(array('itemid'=>$this->id, 'userid'=>$userid), false);
+            $final->insert();
+            $final->grade_item =& $this;
+
+        } else if ($final->is_locked()) {
+            // no need to recalculate locked grades
+            return;
+        }
+
+
+        // do the calculation
+        $this->formula->set_params($params);
+        $result = $this->formula->evaluate();
+
+        // store the result
+        if ($result === false) {
+            // error during calculation
+            if (!is_null($final->finalgrade) or !is_null($final->rawgrade)) {
+                $final->finalgrade = null;
+                $final->rawgrade   = null;
+                $final->update();
+            }
+            return false;
+
+        } else {
+            // normalize
+            $result = bounded_number($this->grademin, $result, $this->grademax);
+            if ($this->gradetype == GRADE_TYPE_SCALE) {
+                $result = round($result+0.00001); // round scales upwards
+            }
+
+            // store only if final grade changed, remove raw grade because we do not need it
+            if ($final->finalgrade != $result or !is_null($final->rawgrade)) {
+                $final->finalgrade = $result;
+                $final->rawgrade   = null;
+                $final->update();
+            }
+            return true;
+        }
+    }
+
 }
 ?>
index 6e90a0e8ff6560ffe88ff8250fd42d361ced14fe..c61e680e8473f586665ed02fb13917138bdd0ea0 100644 (file)
@@ -93,6 +93,7 @@ class grade_outcome extends grade_object {
     
     /**
      * Finds and returns a grade_outcome object based on 1-3 field values.
+     * @static
      *
      * @param boolean $static Unless set to true, this method will also set $this object with the returned values.
      * @param string $field1
@@ -106,16 +107,9 @@ class grade_outcome extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") { 
         if ($grade_outcome = get_record('grade_outcomes', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_outcome') {
-                print_object($this);
-                foreach ($grade_outcome as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_outcome = new grade_outcome($grade_outcome);
-                return $grade_outcome;
-            }
+            $grade_outcome = new grade_outcome($grade_outcome);
+            return $grade_outcome;
+
         } else {
             return false;
         }
index 38264bc492cb6cf8f82d2647cfe03bd476efe3b6..82a1d22717d27f2ccb6ddeb1bc01497e09ec65d6 100644 (file)
@@ -74,6 +74,7 @@ class grade_scale extends grade_object {
     
     /**
      * Finds and returns a grade_scale object based on 1-3 field values.
+     * @static
      *
      * @param string $field1
      * @param string $value1
@@ -86,15 +87,9 @@ class grade_scale extends grade_object {
      */
     function fetch($field1, $value1, $field2='', $value2='', $field3='', $value3='', $fields="*") { 
         if ($grade_scale = get_record('scale', $field1, $value1, $field2, $value2, $field3, $value3, $fields)) {
-            if (isset($this) && get_class($this) == 'grade_scale') {
-                foreach ($grade_scale as $param => $value) {
-                    $this->$param = $value;
-                }
-                return $this;
-            } else {
-                $grade_scale = new grade_scale($grade_scale);
-                return $grade_scale;
-            }
+            $grade_scale = new grade_scale($grade_scale);
+            return $grade_scale;
+
         } else {
             return false;
         }
index 13ebbc867e53748fbeaf1ce49ce10587bb63d5b7..6302ecd104f8e87a8b156bfcd14d955f3f7ecd4b 100644 (file)
@@ -59,7 +59,6 @@ define('GRADE_UPDATE_ITEM_LOCKED', 4);
 
 require_once($CFG->libdir . '/grade/grade_category.php');
 require_once($CFG->libdir . '/grade/grade_item.php');
-require_once($CFG->libdir . '/grade/grade_calculation.php');
 require_once($CFG->libdir . '/grade/grade_grades.php');
 require_once($CFG->libdir . '/grade/grade_scale.php');
 require_once($CFG->libdir . '/grade/grade_outcome.php');
@@ -404,10 +403,10 @@ function grade_update_final_grades($courseid, $regradeall=false) {
             }
 
             //do we have all data for finalizing of this item?
-            $dependson = $grade_item->dependson();
+            $depends_on = $grade_item->depends_on();
 
             $doupdate = true;
-            foreach ($dependson as $did) {
+            foreach ($depends_on as $did) {
                 if (!in_array($did, $finalids)) {
                     $doupdate = false;
                 }
index ca329681026c55c9695c6e821d024d9df6510a6d..553cb1aecbe37c30b88c699e4c53e9cfd5a12808 100644 (file)
@@ -54,7 +54,6 @@ class grade_test extends UnitTestCase {
     var $tables = array('grade_categories',
                         'scale',
                         'grade_items',
-                        'grade_calculations',
                         'grade_grades',
                         'grade_grades_text',
                         'grade_outcomes',
@@ -62,7 +61,6 @@ class grade_test extends UnitTestCase {
 
     var $grade_items = array();
     var $grade_categories = array();
-    var $grade_calculations = array();
     var $grade_grades = array();
     var $grade_grades_text = array();
     var $grade_outcomes = array();
@@ -108,6 +106,7 @@ class grade_test extends UnitTestCase {
             $table->addFieldInfo('itemnumber', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
             $table->addFieldInfo('iteminfo', XMLDB_TYPE_TEXT, 'medium', null, XMLDB_NOTNULL, null, null, null, null);
             $table->addFieldInfo('idnumber', XMLDB_TYPE_CHAR, '255', null, null, null, null, null, null);
+            $table->addFieldInfo('calculation', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null);
             $table->addFieldInfo('gradetype', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null, null, '1');
             $table->addFieldInfo('grademax', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, null, null, '100');
             $table->addFieldInfo('grademin', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, null, null, '0');
@@ -158,28 +157,6 @@ class grade_test extends UnitTestCase {
             $result = $result && create_table($table, true, false);
         }
 
-        /// Define table grade_calculations to be created
-        $table = new XMLDBTable('grade_calculations');
-        
-        if ($result && !table_exists($table)) {
-
-            /// Adding fields to table grade_calculations
-            $table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null, null);
-            $table->addFieldInfo('itemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null);
-            $table->addFieldInfo('calculation', XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null);
-            $table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
-            $table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
-            $table->addFieldInfo('usermodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
-
-            /// Adding keys to table grade_calculations
-            $table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
-            $table->addKeyInfo('itemid', XMLDB_KEY_FOREIGN, array('itemid'), 'grade_items', array('id'));
-            $table->addKeyInfo('usermodified', XMLDB_KEY_FOREIGN, array('usermodified'), 'user', array('id'));
-
-            /// Launch create table for grade_calculations
-            $result = $result && create_table($table, true, false);
-        }
-
         /// Define table grade_grades_text to be created
         $table = new XMLDBTable('grade_grades_text');
         
@@ -493,6 +470,7 @@ class grade_test extends UnitTestCase {
         $grade_item->grademin = 30;
         $grade_item->grademax = 110;
         $grade_item->itemnumber = 1;
+        $grade_item->idnumber = 'item id 0';
         $grade_item->iteminfo = 'Grade item used for unit testing';
         $grade_item->timecreated = mktime();
         $grade_item->timemodified = mktime();
@@ -510,6 +488,7 @@ class grade_test extends UnitTestCase {
         $grade_item->itemname = 'unittestgradeitem2';
         $grade_item->itemtype = 'import';
         $grade_item->itemmodule = 'assignment';
+        $grade_item->calculation = '= [#gi'.$this->grade_items[0]->id.'#] + 30 + [item id 0] - [item id 0]';
         $grade_item->gradetype = GRADE_TYPE_VALUE;
         $grade_item->iteminstance = 2;
         $grade_item->itemnumber = null;
@@ -698,23 +677,6 @@ class grade_test extends UnitTestCase {
 
     }
 
-    /**
-     * Load grade_calculation data into the database, and adds the corresponding objects to this class' variable.
-     */
-    function load_grade_calculations() {
-        // Calculation for grade_item 2
-        $grade_calculation = new stdClass();
-        $grade_calculation->itemid = $this->grade_items[1]->id;
-        $grade_calculation->calculation = '= gi'.$this->grade_items[0]->id.' + 30 ';
-        $grade_calculation->timecreated = mktime();
-        $grade_calculation->timemodified = mktime();
-        
-        if ($grade_calculation->id = insert_record('grade_calculations', $grade_calculation)) {
-            $this->grade_calculations[0] = $grade_calculation;
-            $this->grade_items[1]->calculation = $grade_calculation;
-        } 
-    }
-
     /**
      * Load grade_grades data into the database, and adds the corresponding objects to this class' variable.
      */
diff --git a/lib/simpletest/grade/simpletest/testgradecalculation.php b/lib/simpletest/grade/simpletest/testgradecalculation.php
deleted file mode 100644 (file)
index 5832d8f..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php // $Id$
-
-///////////////////////////////////////////////////////////////////////////
-//                                                                       //
-// NOTICE OF COPYRIGHT                                                   //
-//                                                                       //
-// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
-//          http://moodle.org                                            //
-//                                                                       //
-// Copyright (C) 1999-2004  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                         //
-//                                                                       //
-///////////////////////////////////////////////////////////////////////////
-
-/**
- * Unit tests for grade_calculation object.
- *
- * @author nicolas@moodle.com
- * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @package moodlecore
- */
-
-if (!defined('MOODLE_INTERNAL')) {
-    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
-}
-
-require_once($CFG->libdir.'/simpletest/fixtures/gradetest.php');
-
-class grade_calculation_test extends grade_test {
-
-    function test_grade_calculation_construct() {
-        $params = new stdClass();
-
-        $params->itemid = $this->grade_items[0]->id;
-        $params->calculation = '=MEAN(1, 2)';
-
-        $grade_calculation = new grade_calculation($params, false);
-        $this->assertEqual($params->itemid, $grade_calculation->itemid);
-        $this->assertEqual($params->calculation, $grade_calculation->calculation);
-    }
-
-    function test_grade_calculation_insert() {
-        $grade_calculation = new grade_calculation();
-        $this->assertTrue(method_exists($grade_calculation, 'insert'));
-
-        $grade_calculation->itemid = $this->grade_items[0]->id;
-        $grade_calculation->calculation = '=MEAN(1, 2)';
-
-        $grade_calculation->insert();
-
-        $last_grade_calculation = end($this->grade_calculations);
-
-        $this->assertEqual($grade_calculation->id, $last_grade_calculation->id + 1);
-        $this->assertFalse(empty($grade_calculation->timecreated));
-        $this->assertFalse(empty($grade_calculation->timemodified));
-
-    }
-
-    function test_grade_calculation_update() {
-        $grade_calculation = new grade_calculation($this->grade_calculations[0]);
-        $this->assertTrue(method_exists($grade_calculation, 'update'));
-        $grade_calculation->calculation = '=MEAN(1, 2)';
-        $this->assertTrue($grade_calculation->update());
-        $calculation = get_field('grade_calculations', 'calculation', 'id', $this->grade_calculations[0]->id);
-        $this->assertEqual($grade_calculation->calculation, $calculation);
-    }
-
-    function test_grade_calculation_delete() {
-        $grade_calculation = new grade_calculation($this->grade_calculations[0]);
-        $this->assertTrue(method_exists($grade_calculation, 'delete'));
-
-        $this->assertTrue($grade_calculation->delete());
-        $this->assertFalse(get_record('grade_calculations', 'id', $grade_calculation->id));
-    }
-
-    function test_grade_calculation_fetch() {
-        $grade_calculation = new grade_calculation();
-        $this->assertTrue(method_exists($grade_calculation, 'fetch'));
-
-        $grade_calculation = grade_calculation::fetch('id', $this->grade_calculations[0]->id);
-        $this->assertEqual($this->grade_calculations[0]->id, $grade_calculation->id);
-        $this->assertEqual($this->grade_calculations[0]->calculation, $grade_calculation->calculation);
-    }
-
-    function test_grade_calculation_compute() {
-        $grade_calculation = new grade_calculation($this->grade_calculations[0]);
-        $this->assertTrue(method_exists($grade_calculation, 'compute'));
-
-        $grade_item = $grade_calculation->load_grade_item();
-
-        $grade_grades = grade_grades::fetch('id', $this->grade_grades[3]->id);
-        $grade_grades->delete();
-        $grade_grades = grade_grades::fetch('id', $this->grade_grades[4]->id);
-        $grade_grades->delete();
-        $grade_grades = grade_grades::fetch('id', $this->grade_grades[5]->id);
-        $grade_grades->delete();
-
-        $grade_calculation->compute();
-
-        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[3]->userid, 'itemid', $this->grade_grades[3]->itemid);
-        $this->assertEqual($this->grade_grades[3]->finalgrade, $grade_grades->finalgrade);
-        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[4]->userid, 'itemid', $this->grade_grades[4]->itemid);
-        $this->assertEqual($this->grade_grades[4]->finalgrade, $grade_grades->finalgrade);
-        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[5]->userid, 'itemid', $this->grade_grades[5]->itemid);
-        $this->assertEqual($this->grade_grades[5]->finalgrade, $grade_grades->finalgrade);
-    }
-
-}
-?>
index f8cc1e615510aae29f260621b223fb3eabf9848d..f61f68ad1c6634a20738acba0a1d9d5d3ac25e90 100755 (executable)
@@ -232,24 +232,6 @@ class grade_item_test extends grade_test {
         $this->assertEqual($this->grade_grades[0]->finalgrade, $final_grade->finalgrade);\r
     }\r
 \r
-    function test_grade_item_is_calculated() {\r
-        $grade_item = new grade_item($this->grade_items[1]);\r
-        $this->assertTrue(method_exists($grade_item, 'is_calculated'));\r
-        $this->assertTrue($grade_item->is_calculated());\r
-    }\r
-\r
-    function test_grade_item_set_calculation() {\r
-/*        $grade_item = new grade_item($this->grade_items[1]);\r
-        $this->assertTrue(method_exists($grade_item, 'set_calculation'));\r
-        $this->assertTrue(method_exists($grade_item, 'is_calculated'));\r
-\r
-        $calculation = '=SUM([unittestgradeitem1], [unittestgradeitem3])';\r
-        $grade_item->set_calculation($calculation);\r
-        $new_calculation = $grade_item->is_calculated();\r
-\r
-        $this->assertEqual($calculation, $new_calculation->calculation);\r
-*/    }\r
-\r
     function test_grade_item_get_category() {\r
         $grade_item = new grade_item($this->grade_items[0]);\r
         $this->assertTrue(method_exists($grade_item, 'get_category'));\r
@@ -330,6 +312,9 @@ class grade_item_test extends grade_test {
         $this->assertEqual(round(1.6), round($grade_item->adjust_grade($grade_raw->rawgrade, $grade_raw->grademin, $grade_raw->grademax)));\r
     }\r
 \r
+    /**\r
+     * Test locking of grade items\r
+     */\r
     function test_grade_item_set_locked() {\r
         $grade_item = new grade_item($this->grade_items[0]);\r
         $this->assertTrue(method_exists($grade_item, 'set_locked'));\r
@@ -362,11 +347,28 @@ class grade_item_test extends grade_test {
         $this->assertTrue($grade_item->is_locked(1));\r
     }\r
 \r
-    function test_grade_item_dependson() {\r
-        $grade_item = new grade_item($this->grade_items[0]);\r
-        //TODO\r
-    }\r
+    function test_grade_item_depends_on() {\r
+        $grade_item = new grade_item($this->grade_items[1]);\r
 \r
+        // calculated grade dependency\r
+        $deps = $grade_item->depends_on();\r
+        sort($deps, SORT_NUMERIC); // for comparison\r
+        $this->assertEqual(array($this->grade_items[0]->id), $deps);\r
+\r
+        // simulate depends on returns none when locked\r
+        $grade_item->locked = time();\r
+        $grade_item->update();\r
+        $deps = $grade_item->depends_on();\r
+        sort($deps, SORT_NUMERIC); // for comparison\r
+        $this->assertEqual(array(), $deps);\r
+\r
+        // category dependency\r
+        $grade_item = new grade_item($this->grade_items[3]);\r
+        $deps = $grade_item->depends_on();\r
+        sort($deps, SORT_NUMERIC); // for comparison\r
+        $res = array($this->grade_items[4]->id, $this->grade_items[5]->id);\r
+        $this->assertEqual($res, $deps);\r
+    }\r
 \r
 /*\r
     function test_grade_item_toggle_hiding() {\r
@@ -383,12 +385,65 @@ class grade_item_test extends grade_test {
         $this->assertEqual(3, $grade_item->toggle_hiding(true));\r
         $this->assertTrue($grade_item->hidden);\r
         $this->assertTrue($grade_item->grade_grades[1]->hidden);\r
-        $this->assertTrue($grade_item->grade_grades[2]->hidden);\r
+        $this->assertTrue($grade_item->grade_gra\r
+        des[2]->hidden);\r
         $this->assertTrue($grade_item->grade_grades[3]->hidden);\r
     }\r
 */\r
 \r
-    function test_float_keys() {\r
+    function test_grade_item_is_calculated() {\r
+        $grade_item = new grade_item($this->grade_items[1]);\r
+        $this->assertTrue(method_exists($grade_item, 'is_calculated'));\r
+        $grade_itemsource = new grade_item($this->grade_items[0]);\r
+        $normalizedformula = str_replace('['.$grade_itemsource->idnumber.']', '[#gi'.$grade_itemsource->id.'#]', $this->grade_items[1]->calculation);\r
+\r
+        $this->assertTrue($grade_item->is_calculated());\r
+        $this->assertEqual($normalizedformula, $grade_item->calculation);\r
+    }\r
+\r
+    function test_grade_item_set_calculation() {\r
+        $grade_item = new grade_item($this->grade_items[1]);\r
+        $this->assertTrue(method_exists($grade_item, 'set_calculation'));\r
+        $grade_itemsource = new grade_item($this->grade_items[0]);\r
+\r
+        $grade_item->set_calculation('=['.$grade_itemsource->idnumber.']');\r
+\r
+        $this->assertTrue(!empty($grade_item->needsupdate));\r
+        $this->assertEqual('=[#gi'.$grade_itemsource->id.'#]', $grade_item->calculation);\r
     }\r
+\r
+    function test_grade_item_get_calculation() {\r
+        $grade_item = new grade_item($this->grade_items[1]);\r
+        $this->assertTrue(method_exists($grade_item, 'get_calculation'));\r
+        $grade_itemsource = new grade_item($this->grade_items[0]);\r
+\r
+        $denormalizedformula = str_replace('[#gi'.$grade_itemsource->id.'#]', '['.$grade_itemsource->idnumber.']', $this->grade_items[1]->calculation);\r
+\r
+        $formula = $grade_item->get_calculation();\r
+        $this->assertTrue(!empty($grade_item->needsupdate));\r
+        $this->assertEqual($denormalizedformula, $formula);\r
+    }\r
+\r
+    function test_grade_item_compute() {\r
+        $grade_item = new grade_item($this->grade_items[1]);\r
+        $this->assertTrue(method_exists($grade_item, 'compute'));\r
+\r
+        $grade_grades = grade_grades::fetch('id', $this->grade_grades[3]->id);\r
+        $grade_grades->delete();\r
+        $grade_grades = grade_grades::fetch('id', $this->grade_grades[4]->id);\r
+        $grade_grades->delete();\r
+        $grade_grades = grade_grades::fetch('id', $this->grade_grades[5]->id);\r
+        $grade_grades->delete();\r
+\r
+        $grade_item->compute();\r
+\r
+        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[3]->userid, 'itemid', $this->grade_grades[3]->itemid);\r
+        $this->assertEqual($this->grade_grades[3]->finalgrade, $grade_grades->finalgrade);\r
+        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[4]->userid, 'itemid', $this->grade_grades[4]->itemid);\r
+        $this->assertEqual($this->grade_grades[4]->finalgrade, $grade_grades->finalgrade);\r
+        $grade_grades = grade_grades::fetch('userid', $this->grade_grades[5]->userid, 'itemid', $this->grade_grades[5]->itemid);\r
+        $this->assertEqual($this->grade_grades[5]->finalgrade, $grade_grades->finalgrade);\r
+    }\r
+\r
 }\r
 ?>\r
index b005215a539dc3a90b328a3acc7ea82751f25bfd..5c17d344283fbeab3359031976b8eb7e425d4c1a 100644 (file)
@@ -6,7 +6,7 @@
 // This is compared against the values stored in the database to determine
 // whether upgrades should be performed (see lib/db/*.php)
 
-   $version = 2007062008;  // YYYYMMDD = date
+   $version = 2007062301;  // YYYYMMDD = date
                            //       XY = increments within a single day
 
    $release = '1.9 dev';    // Human-friendly version name