]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9643 some more polishing
authorskodak <skodak>
Sat, 26 May 2007 12:59:13 +0000 (12:59 +0000)
committerskodak <skodak>
Sat, 26 May 2007 12:59:13 +0000 (12:59 +0000)
lib/evalmath/evalmath.class.php
lib/mathslib.php
lib/simpletest/testmathslib.php

index 2270d626e01f6689ed4c9bf5ac71727ff0ab1bdd..37a419715c1ae5a16786daabc73060e47272be76 100644 (file)
@@ -86,6 +86,12 @@ LICENSE
 \r
 */\r
 \r
+/**\r
+ * This class was heavily modified in order to get usefull spreadsheet emulation ;-)\r
+ * skodak\r
+ * \r
+ */\r
+\r
 class EvalMath {\r
 \r
     var $suppress_errors = false;\r
@@ -93,15 +99,17 @@ class EvalMath {
     \r
     var $v = array(); // variables (and constants)\r
     var $f = array(); // user-defined functions\r
-    var $vb = array('e', 'pi'); // constants\r
+    var $vb = array(); // constants\r
     var $fb = array(  // built-in functions\r
         'sin','sinh','arcsin','asin','arcsinh','asinh',\r
         'cos','cosh','arccos','acos','arccosh','acosh',\r
         'tan','tanh','arctan','atan','arctanh','atanh',\r
-        'sqrt','abs','ln','log');\r
+        'sqrt','abs','ln','log','exp');\r
 \r
     var $fc = array( // calc functions emulation\r
-        'sum'=>array(-1), 'pi'=>array(0), 'power'=>array(2), 'round'=>array(2,1), 'average'=>array(-1));\r
+        'average'=>array(-1), 'max'=>array(-1),  'min'=>array(-1),\r
+        'mod'=>array(2),      'pi'=>array(0),    'power'=>array(2),\r
+        'round'=>array(1, 2), 'sum'=>array(-1));\r
     \r
     function EvalMath() {\r
     }\r
@@ -151,10 +159,7 @@ class EvalMath {
     }\r
     \r
     function vars() {\r
-        $output = $this->v;\r
-        unset($output['pi']);\r
-        unset($output['e']);\r
-        return $output;\r
+        return $this->v;\r
     }\r
     \r
     function funcs() {\r
@@ -424,16 +429,41 @@ class EvalMathStack {
 // spreadsheed functions emulation\r
 // watch out for reversed args!!\r
 class EvalMathCalcEmul {\r
+\r
     function average($args) {\r
         return (EvalMathCalcEmul::sum($args)/count($args));\r
     }\r
 \r
+    function max($args) {\r
+        $res = array_pop($args);\r
+        foreach($args as $a) {\r
+            if ($res < $a) {\r
+                $res = $a;\r
+            }\r
+        }\r
+        return $res;\r
+    }\r
+\r
+    function min($args) {\r
+        $res = array_pop($args);\r
+        foreach($args as $a) {\r
+            if ($res > $a) {\r
+                $res = $a;\r
+            }\r
+        }\r
+        return $res;\r
+    }\r
+\r
+    function mod($args) {\r
+        return $args[1] % $args[0];\r
+    }\r
+\r
     function pi($args) {\r
         return pi();\r
     }\r
 \r
     function power($args) {\r
-        return $args[0]^$args[0];\r
+        return $args[1]^$args[0];\r
     }\r
 \r
     function round($args) {\r
@@ -447,7 +477,7 @@ class EvalMathCalcEmul {
     function sum($args) {\r
         $res = 0;\r
         foreach($args as $a) {\r
-           $res += $a; \r
+           $res += $a;\r
         }\r
         return $res;\r
     }\r
index fa4f7abfd0e42a11f883b5ba5adc96188f7aabfb..3eb9cb41a4ce5b2f9d32ba78538cd289b12f09d9 100644 (file)
@@ -2,55 +2,86 @@
 
 require_once $CFG->dirroot.'/lib/evalmath/evalmath.class.php';
 
+/**
+ * This class abstracts evaluation of spreadsheet formulas.
+ * See unit tests in lib/simpletest/testmathslib.php for sample usage.
+ *
+ * @author Petr Skoda (skodak)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ */
 class calc_formula {
 
-    var $em;
-    var $nfx = false;
-    var $error = false;
+    // private properties
+    var $_em;
+    var $_nfx = false;   // postfix expression
+    var $_error = false; // last error
 
+    /**
+     * Constructor for spreadsheet formula with optional parameters
+     *
+     * @param string $formula with leading =
+     * @param array $params associative array of parameters used in formula. All parameter names must be lowercase!
+     */
     function calc_formula($formula, $params=false) {
-        $this->em = new EvalMath();
-        $this->em->suppress_errors = true;
+        $this->_em = new EvalMath();
+        $this->_em->suppress_errors = true;
         if (strpos($formula, '=') !== 0) {
-            $this->error = "missing '='";
+            $this->_error = "missing '='";
             return;
         }
         $formula = substr($formula, 1);
         if (strpos($formula, '=') !== false) {
-            $this->error = "too many '='";
+            $this->_error = "too many '='";
             return;
         }
-        $this->nfx = $this->em->nfx($formula);
-        if ($this->nfx == false) {
-            $this->error = $this->em->last_error;
+        $this->_nfx = $this->_em->nfx($formula);
+        if ($this->_nfx == false) {
+            $this->_error = $this->_em->last_error;
             return;
         }
         if ($params != false) {
-            $this->em->v = $params;
+            $this->set_params($params);
         }
     }
 
+    /**
+     * Raplace parameters used in calculation
+     *
+     * @param array $params associative array of parameters used in formula. All parameter names must be lowercase!
+     */
     function set_params($params) {
-        $this->em->v = $params;
+        $this->_em->v = $params;
     }
 
+    /**
+     * Evaluate formula
+     *
+     * @return mixed number if ok, false if error
+     */
     function evaluate() {
-        if ($this->nfx == false) {
+        if ($this->_nfx == false) {
             return false;
         }
-        $res = $this->em->pfx($this->nfx);
+        $res = $this->_em->pfx($this->_nfx);
         if ($res === false) {
-            $this->error = $this->em->last_error;
+            $this->_error = $this->_em->last_error;
             return false;
         } else {
-            $this->error = false;
+            $this->_error = false;
             return $res;
         }
 
     }
 
+    /**
+     * Get last error.
+     *
+     * TODO: localize the strings
+     *
+     * @return mixed string with last error description or false if ok
+     */
     function get_error() {
-        return $this->error;
+        return $this->_error;
     }
 }
 
index 783fdd3c285051179a1b24eede2470ae7453cc73..4f6d02e16b49846c6a080d3496e188972c923773 100755 (executable)
@@ -1,7 +1,5 @@
 <?php
 
-/* $Id$ */
-
 if (!defined('MOODLE_INTERNAL')) {
     die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
 }
@@ -10,10 +8,16 @@ global $CFG;
 require_once($CFG->libdir . '/simpletestlib.php');
 require_once($CFG->libdir . '/mathslib.php');
 
+/**
+ * Unit tests of mathslib wrapper and underlying EvalMath library.
+ *
+ * @author Petr Skoda (skodak)
+ * @version $Id$
+ */
 class mathsslib_test extends UnitTestCase {
 
     /**
-     * Tests the basic formula execition
+     * Tests the basic formula evaluation
      */
     function test__basic() {
         $formula = new calc_formula('=1+2');
@@ -31,7 +35,19 @@ class mathsslib_test extends UnitTestCase {
     }
 
     /**
-     * Tests the formula params
+     * Tests the changed params
+     */
+    function test__changing_params() {
+        $formula = new calc_formula('=a+b+c', array('a'=>10,'b'=>20,'c'=>30));
+        $res = $formula->evaluate();
+        $this->assertEqual($res, 60, '10+20+30 is: %s');
+        $formula->set_params(array('a'=>1,'b'=>2,'c'=>3));
+        $res = $formula->evaluate();
+        $this->assertEqual($res, 6, 'changed params 1+2+3 is: %s');
+    }
+
+    /**
+     * Tests the spreadsheet emulation function in formula
      */
     function test__calc_function() {
         $formula = new calc_formula('=sum(a,b,c)', array('a'=>10,'b'=>20,'c'=>30));
@@ -40,15 +56,15 @@ class mathsslib_test extends UnitTestCase {
     }
 
     /**
-     * Tests the formula changed params
+     * Tests the min and max functions
      */
-    function test__changing_params() {
-        $formula = new calc_formula('=a+b+c', array('a'=>10,'b'=>20,'c'=>30));
+    function test__minmax_function() {
+        $formula = new calc_formula('=min(a,b,c)', array('a'=>10,'b'=>20,'c'=>30));
         $res = $formula->evaluate();
-        $this->assertEqual($res, 60, '10+20+30 is: %s');
-        $formula->set_params(array('a'=>1,'b'=>2,'c'=>3));
+        $this->assertEqual($res, 10, 'minimum is: %s');
+        $formula = new calc_formula('=max(a,b,c)', array('a'=>10,'b'=>20,'c'=>30));
         $res = $formula->evaluate();
-        $this->assertEqual($res, 6, 'changed params - 1+2+3 is: %s');
+        $this->assertEqual($res, 30, 'maximum is: %s');
     }
 
 }