mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
MDL-10231 merge grade_calculations and grade_items table + calculation improvements
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.
This commit is contained in:
parent
d0c92410ef
commit
61c33818d5
@ -1492,6 +1492,8 @@
|
||||
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));
|
||||
@ -1504,7 +1506,6 @@
|
||||
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);
|
||||
@ -1553,27 +1554,6 @@
|
||||
|
||||
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) {
|
||||
|
||||
@ -1581,19 +1561,19 @@
|
||||
|
||||
$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));
|
||||
@ -1611,7 +1591,7 @@
|
||||
|
||||
$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) {
|
||||
@ -1635,7 +1615,7 @@
|
||||
|
||||
$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) {
|
||||
|
@ -1445,6 +1445,7 @@
|
||||
$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
|
||||
@ -1499,7 +1500,7 @@
|
||||
|
||||
$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++) {
|
||||
@ -1542,37 +1543,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/// 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'])) {
|
||||
|
@ -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"
|
||||
>
|
||||
@ -1247,8 +1247,9 @@
|
||||
<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"/>
|
||||
@ -1273,7 +1274,7 @@
|
||||
<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"/>
|
||||
@ -1293,22 +1294,7 @@
|
||||
<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"/>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
return !empty($this->calculation);
|
||||
/*
|
||||
* 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 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->calculation = $formula;
|
||||
}
|
||||
|
||||
$this->force_regrading();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
@ -232,24 +232,6 @@ class grade_item_test extends grade_test {
|
||||
$this->assertEqual($this->grade_grades[0]->finalgrade, $final_grade->finalgrade);
|
||||
}
|
||||
|
||||
function test_grade_item_is_calculated() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'is_calculated'));
|
||||
$this->assertTrue($grade_item->is_calculated());
|
||||
}
|
||||
|
||||
function test_grade_item_set_calculation() {
|
||||
/* $grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'set_calculation'));
|
||||
$this->assertTrue(method_exists($grade_item, 'is_calculated'));
|
||||
|
||||
$calculation = '=SUM([unittestgradeitem1], [unittestgradeitem3])';
|
||||
$grade_item->set_calculation($calculation);
|
||||
$new_calculation = $grade_item->is_calculated();
|
||||
|
||||
$this->assertEqual($calculation, $new_calculation->calculation);
|
||||
*/ }
|
||||
|
||||
function test_grade_item_get_category() {
|
||||
$grade_item = new grade_item($this->grade_items[0]);
|
||||
$this->assertTrue(method_exists($grade_item, 'get_category'));
|
||||
@ -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)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test locking of grade items
|
||||
*/
|
||||
function test_grade_item_set_locked() {
|
||||
$grade_item = new grade_item($this->grade_items[0]);
|
||||
$this->assertTrue(method_exists($grade_item, 'set_locked'));
|
||||
@ -362,11 +347,28 @@ class grade_item_test extends grade_test {
|
||||
$this->assertTrue($grade_item->is_locked(1));
|
||||
}
|
||||
|
||||
function test_grade_item_dependson() {
|
||||
$grade_item = new grade_item($this->grade_items[0]);
|
||||
//TODO
|
||||
}
|
||||
function test_grade_item_depends_on() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
|
||||
// calculated grade dependency
|
||||
$deps = $grade_item->depends_on();
|
||||
sort($deps, SORT_NUMERIC); // for comparison
|
||||
$this->assertEqual(array($this->grade_items[0]->id), $deps);
|
||||
|
||||
// simulate depends on returns none when locked
|
||||
$grade_item->locked = time();
|
||||
$grade_item->update();
|
||||
$deps = $grade_item->depends_on();
|
||||
sort($deps, SORT_NUMERIC); // for comparison
|
||||
$this->assertEqual(array(), $deps);
|
||||
|
||||
// category dependency
|
||||
$grade_item = new grade_item($this->grade_items[3]);
|
||||
$deps = $grade_item->depends_on();
|
||||
sort($deps, SORT_NUMERIC); // for comparison
|
||||
$res = array($this->grade_items[4]->id, $this->grade_items[5]->id);
|
||||
$this->assertEqual($res, $deps);
|
||||
}
|
||||
|
||||
/*
|
||||
function test_grade_item_toggle_hiding() {
|
||||
@ -383,12 +385,65 @@ class grade_item_test extends grade_test {
|
||||
$this->assertEqual(3, $grade_item->toggle_hiding(true));
|
||||
$this->assertTrue($grade_item->hidden);
|
||||
$this->assertTrue($grade_item->grade_grades[1]->hidden);
|
||||
$this->assertTrue($grade_item->grade_grades[2]->hidden);
|
||||
$this->assertTrue($grade_item->grade_gra
|
||||
des[2]->hidden);
|
||||
$this->assertTrue($grade_item->grade_grades[3]->hidden);
|
||||
}
|
||||
*/
|
||||
|
||||
function test_float_keys() {
|
||||
function test_grade_item_is_calculated() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'is_calculated'));
|
||||
$grade_itemsource = new grade_item($this->grade_items[0]);
|
||||
$normalizedformula = str_replace('['.$grade_itemsource->idnumber.']', '[#gi'.$grade_itemsource->id.'#]', $this->grade_items[1]->calculation);
|
||||
|
||||
$this->assertTrue($grade_item->is_calculated());
|
||||
$this->assertEqual($normalizedformula, $grade_item->calculation);
|
||||
}
|
||||
|
||||
function test_grade_item_set_calculation() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'set_calculation'));
|
||||
$grade_itemsource = new grade_item($this->grade_items[0]);
|
||||
|
||||
$grade_item->set_calculation('=['.$grade_itemsource->idnumber.']');
|
||||
|
||||
$this->assertTrue(!empty($grade_item->needsupdate));
|
||||
$this->assertEqual('=[#gi'.$grade_itemsource->id.'#]', $grade_item->calculation);
|
||||
}
|
||||
|
||||
function test_grade_item_get_calculation() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'get_calculation'));
|
||||
$grade_itemsource = new grade_item($this->grade_items[0]);
|
||||
|
||||
$denormalizedformula = str_replace('[#gi'.$grade_itemsource->id.'#]', '['.$grade_itemsource->idnumber.']', $this->grade_items[1]->calculation);
|
||||
|
||||
$formula = $grade_item->get_calculation();
|
||||
$this->assertTrue(!empty($grade_item->needsupdate));
|
||||
$this->assertEqual($denormalizedformula, $formula);
|
||||
}
|
||||
|
||||
function test_grade_item_compute() {
|
||||
$grade_item = new grade_item($this->grade_items[1]);
|
||||
$this->assertTrue(method_exists($grade_item, 'compute'));
|
||||
|
||||
$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_item->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);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user