MDL-9137 various grading improvements

1/ initial support for migration of old grade_items and categories (not tested)
2/ rewritten grade update and calculation logic
3/ initial support for calculation formulas
4/ minor API refactoring and cleanup
5/ various small bugfixes
6/ fixed use of grademax with scales
7/ fixed some unit tests

TODO:
* implement proper locking of grades - needs discussion
* force recalculation of all formulas after adding/removing/changing of grade items
* better delete flag support
* support for NULLs n backup - Eloy already proposed a solution
* support for NULLs in set_field()
* speedup
* more unit tests nd functional tests
This commit is contained in:
skodak
2007-06-18 13:43:40 +00:00
parent 75bca47db0
commit b8ff92b66b
14 changed files with 895 additions and 777 deletions
+8 -8
View File
@@ -124,7 +124,7 @@ class EvalMath {
if (substr($expr, -1, 1) == ';') $expr = substr($expr, 0, strlen($expr)-1); // strip semicolons at the end
//===============
// is it a variable assignment?
if (preg_match('/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches)) {
if (preg_match('/^\s*([a-z][a-z0-9]*)\s*=\s*(.+)$/', $expr, $matches)) {
if (in_array($matches[1], $this->vb)) { // make sure we're not assigning to a constant
return $this->trigger("cannot assign to constant '$matches[1]'");
}
@@ -133,7 +133,7 @@ class EvalMath {
return $this->v[$matches[1]]; // and return the resulting value
//===============
// is it a function assignment?
} elseif (preg_match('/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches)) {
} elseif (preg_match('/^\s*([a-z][a-z0-9]*)\s*\(\s*([a-z][a-z0-9]*(?:\s*,\s*[a-z][a-z0-9]*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches)) {
$fnn = $matches[1]; // get the function name
if (in_array($matches[1], $this->fb)) { // make sure it isn't built in
return $this->trigger("cannot redefine built-in function '$matches[1]()'");
@@ -142,7 +142,7 @@ class EvalMath {
if (($stack = $this->nfx($matches[3])) === false) return false; // see if it can be converted to postfix
for ($i = 0; $i<count($stack); $i++) { // freeze the state of the non-argument variables
$token = $stack[$i];
if (preg_match('/^[a-z]\w*$/', $token) and !in_array($token, $args)) {
if (preg_match('/^[a-z][a-z0-9]*$/', $token) and !in_array($token, $args)) {
if (array_key_exists($token, $this->v)) {
$stack[$i] = $this->v[$token];
} else {
@@ -193,7 +193,7 @@ class EvalMath {
while(1) { // 1 Infinite Loop ;)
$op = substr($expr, $index, 1); // get the first character at the current index
// find out if we're currently at the beginning of a number/variable/function/parenthesis/operand
$ex = preg_match('/^([a-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr($expr, $index), $match);
$ex = preg_match('/^([a-z][a-z0-9]*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr($expr, $index), $match);
//===============
if ($op == '-' and !$expecting_op) { // is it a negation instead of a minus?
$stack->push('_'); // put a negation on the stack
@@ -220,7 +220,7 @@ class EvalMath {
if (is_null($o2)) return $this->trigger("unexpected ')'");
else $output[] = $o2;
}
if (preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches)) { // did we just close a function?
if (preg_match("/^([a-z][a-z0-9]*)\($/", $stack->last(2), $matches)) { // did we just close a function?
$fnn = $matches[1]; // get the function name
$arg_count = $stack->pop(); // see how many arguments there were (cleverly stored on the stack, thank you)
$fn = $stack->pop();
@@ -248,7 +248,7 @@ class EvalMath {
else $output[] = $o2; // pop the argument expression stuff and push onto the output
}
// make sure there was a function
if (!preg_match("/^([a-z]\w*)\($/", $stack->last(2), $matches))
if (!preg_match("/^([a-z][a-z0-9]*)\($/", $stack->last(2), $matches))
return $this->trigger("unexpected ','");
$stack->push($stack->pop()+1); // increment the argument count
$stack->push('('); // put the ( back on, we'll need to pop back to it again
@@ -263,7 +263,7 @@ class EvalMath {
} elseif ($ex and !$expecting_op) { // do we now have a function/variable/number?
$expecting_op = true;
$val = $match[1];
if (preg_match("/^([a-z]\w*)\($/", $val, $matches)) { // may be func, or variable w/ implicit multiplication against parentheses...
if (preg_match("/^([a-z][a-z0-9]*)\($/", $val, $matches)) { // may be func, or variable w/ implicit multiplication against parentheses...
if (in_array($matches[1], $this->fb) or array_key_exists($matches[1], $this->f) or array_key_exists($matches[1], $this->fc)) { // it's a func
$stack->push($val);
$stack->push(1);
@@ -281,7 +281,7 @@ class EvalMath {
} elseif ($op == ')') {
//it could be only custom function with no params or general error
if ($stack->last() != '(' or $stack->last(2) != 1) return $this->trigger("unexpected ')'");
if (preg_match("/^([a-z]\w*)\($/", $stack->last(3), $matches)) { // did we just close a function?
if (preg_match("/^([a-z][a-z0-9]*)\($/", $stack->last(3), $matches)) { // did we just close a function?
$stack->pop();// (
$stack->pop();// 1
$fn = $stack->pop();