initial commit
This commit is contained in:
		
							
								
								
									
										57
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "env": {
 | 
				
			||||||
 | 
					    "es6": true,
 | 
				
			||||||
 | 
					    "browser": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "ecmaFeatures": {
 | 
				
			||||||
 | 
					    "modules": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "globals": {
 | 
				
			||||||
 | 
					    "exports": true,
 | 
				
			||||||
 | 
					    "require": true,
 | 
				
			||||||
 | 
					    "ViewHelpers": true,
 | 
				
			||||||
 | 
					    "is": true,
 | 
				
			||||||
 | 
					    "Components": true,
 | 
				
			||||||
 | 
					    "XPCOMUtils": true,
 | 
				
			||||||
 | 
					    "EventEmitter": true,
 | 
				
			||||||
 | 
					    "add_task": true,
 | 
				
			||||||
 | 
					    "info": true,
 | 
				
			||||||
 | 
					    "createHost": true,
 | 
				
			||||||
 | 
					    "promiseTab": true,
 | 
				
			||||||
 | 
					    "ok": true,
 | 
				
			||||||
 | 
					    "TEST_URI_ROOT": true,
 | 
				
			||||||
 | 
					    "TargetFactory": true,
 | 
				
			||||||
 | 
					    "gBrowser": true,
 | 
				
			||||||
 | 
					    "gDevTools": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "rules": {
 | 
				
			||||||
 | 
					    "comma-dangle": [2, "never"],
 | 
				
			||||||
 | 
					    "no-underscore-dangle": 0,
 | 
				
			||||||
 | 
					    "no-cond-assign": 0,
 | 
				
			||||||
 | 
					    "no-undef": 0,
 | 
				
			||||||
 | 
					    "no-console": 0,
 | 
				
			||||||
 | 
					    "no-reserved-keys": 2,
 | 
				
			||||||
 | 
					    "valid-jsdoc": [2, {
 | 
				
			||||||
 | 
					      "requireReturn": false,
 | 
				
			||||||
 | 
					      "requireParamDescription": false,
 | 
				
			||||||
 | 
					      "requireReturnDescription": false
 | 
				
			||||||
 | 
					    }],
 | 
				
			||||||
 | 
					    "max-len": [1, 80],
 | 
				
			||||||
 | 
					    "no-use-before-define": 0,
 | 
				
			||||||
 | 
					    "no-self-compare": 1,
 | 
				
			||||||
 | 
					    "no-sequences": 0,
 | 
				
			||||||
 | 
					    "radix": 2,
 | 
				
			||||||
 | 
					    "wrap-iife": 2,
 | 
				
			||||||
 | 
					    "indent": [2, 2],
 | 
				
			||||||
 | 
					    "brace-style": [2, "1tbs"],
 | 
				
			||||||
 | 
					    "comma-style": [2, "last"],
 | 
				
			||||||
 | 
					    "no-lonely-if": 2,
 | 
				
			||||||
 | 
					    "no-multiple-empty-lines": [2, {"max": 2}],
 | 
				
			||||||
 | 
					    "quotes": 0,
 | 
				
			||||||
 | 
					    "space-after-keywords": [2, "always"],
 | 
				
			||||||
 | 
					    "space-before-blocks": [2, "always"],
 | 
				
			||||||
 | 
					    "space-infix-ops": [2, { "int32Hint": false }],
 | 
				
			||||||
 | 
					    "strict": 0,
 | 
				
			||||||
 | 
					    "global-strict": 0
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
							
								
								
									
										33
									
								
								Gruntfile.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Gruntfile.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					module.exports = function(grunt) {
 | 
				
			||||||
 | 
					  grunt.initConfig({
 | 
				
			||||||
 | 
					    eslint: {
 | 
				
			||||||
 | 
					      target: ['*.js', 'tests/*.js']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    babel: {
 | 
				
			||||||
 | 
					      dist: {
 | 
				
			||||||
 | 
					        files: [{
 | 
				
			||||||
 | 
					          expand: true,
 | 
				
			||||||
 | 
					          src: ['*.js', 'tests/*.js'],
 | 
				
			||||||
 | 
					          dest: 'dist/'
 | 
				
			||||||
 | 
					        }]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    mochaTest: {
 | 
				
			||||||
 | 
					      files: ['dist/tests/*.js']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    watch: {
 | 
				
			||||||
 | 
					      scripts: {
 | 
				
			||||||
 | 
					        files: '**/*.js',
 | 
				
			||||||
 | 
					        tasks: ['eslint', 'babel']
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-eslint');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-contrib-watch');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-babel');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-mocha-test');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  grunt.registerTask('default', [ 'babel']);
 | 
				
			||||||
 | 
					  grunt.registerTask('test', ['babel', 'mochaTest']);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										11
									
								
								constats.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								constats.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Constats
 | 
				
			||||||
 | 
					 * Keys must be UPPERCASE
 | 
				
			||||||
 | 
					 * Values Can be a constant value or a function returning a value
 | 
				
			||||||
 | 
					 *        this function doesn't take any arguments (use case: random constats)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  'PI': Math.PI,
 | 
				
			||||||
 | 
					  'E': Math.E,
 | 
				
			||||||
 | 
					  'RAND': Math.random
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										3
									
								
								dist/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								dist/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					dist
 | 
				
			||||||
							
								
								
									
										35
									
								
								dist/Gruntfile.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								dist/Gruntfile.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function (grunt) {
 | 
				
			||||||
 | 
					  grunt.initConfig({
 | 
				
			||||||
 | 
					    eslint: {
 | 
				
			||||||
 | 
					      target: ['*.js', 'tests/*.js']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    babel: {
 | 
				
			||||||
 | 
					      dist: {
 | 
				
			||||||
 | 
					        files: [{
 | 
				
			||||||
 | 
					          expand: true,
 | 
				
			||||||
 | 
					          src: ['*.js', 'tests/*.js'],
 | 
				
			||||||
 | 
					          dest: 'dist/'
 | 
				
			||||||
 | 
					        }]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    mochaTest: {
 | 
				
			||||||
 | 
					      files: ['dist/tests/*.js']
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    watch: {
 | 
				
			||||||
 | 
					      scripts: {
 | 
				
			||||||
 | 
					        files: '**/*.js',
 | 
				
			||||||
 | 
					        tasks: ['eslint', 'babel']
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-eslint');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-contrib-watch');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-babel');
 | 
				
			||||||
 | 
					  grunt.loadNpmTasks('grunt-mocha-test');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  grunt.registerTask('default', ['babel']);
 | 
				
			||||||
 | 
					  grunt.registerTask('test', ['babel', 'mochaTest']);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										17
									
								
								dist/constats.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								dist/constats.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(exports, '__esModule', {
 | 
				
			||||||
 | 
					  value: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Constats
 | 
				
			||||||
 | 
					 * Keys must be UPPERCASE
 | 
				
			||||||
 | 
					 * Values Can be a constant value or a function returning a value
 | 
				
			||||||
 | 
					 *        this function doesn't take any arguments (use case: random constats)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					exports['default'] = {
 | 
				
			||||||
 | 
					  PI: Math.PI,
 | 
				
			||||||
 | 
					  E: Math.E,
 | 
				
			||||||
 | 
					  RAND: Math.random
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					module.exports = exports['default'];
 | 
				
			||||||
							
								
								
									
										157
									
								
								dist/helpers.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								dist/helpers.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(exports, '__esModule', {
 | 
				
			||||||
 | 
					  value: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					var parseFormat = function parseFormat(a) {
 | 
				
			||||||
 | 
					  var split = a.split('1');
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    left: split[0].length,
 | 
				
			||||||
 | 
					    right: split[1].length
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.parseFormat = parseFormat;
 | 
				
			||||||
 | 
					var isNumber = function isNumber(a) {
 | 
				
			||||||
 | 
					  return !isNaN(+a);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.isNumber = isNumber;
 | 
				
			||||||
 | 
					var parseNumbers = (function (_parseNumbers) {
 | 
				
			||||||
 | 
					  function parseNumbers(_x) {
 | 
				
			||||||
 | 
					    return _parseNumbers.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  parseNumbers.toString = function () {
 | 
				
			||||||
 | 
					    return _parseNumbers.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return parseNumbers;
 | 
				
			||||||
 | 
					})(function (a) {
 | 
				
			||||||
 | 
					  return a.map(function (b) {
 | 
				
			||||||
 | 
					    if (isNumber(b)) {
 | 
				
			||||||
 | 
					      return parseFloat(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (Array.isArray(b)) {
 | 
				
			||||||
 | 
					      return parseNumbers(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return b;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.parseNumbers = parseNumbers;
 | 
				
			||||||
 | 
					var dive = function dive(arr, n) {
 | 
				
			||||||
 | 
					  var result = arr;
 | 
				
			||||||
 | 
					  for (var i = 0; i < n; ++i) {
 | 
				
			||||||
 | 
					    result = result[result.length - 1];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.dive = dive;
 | 
				
			||||||
 | 
					var deep = (function (_deep) {
 | 
				
			||||||
 | 
					  function deep(_x2, _x3) {
 | 
				
			||||||
 | 
					    return _deep.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  deep.toString = function () {
 | 
				
			||||||
 | 
					    return _deep.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return deep;
 | 
				
			||||||
 | 
					})(function (arr, n) {
 | 
				
			||||||
 | 
					  var index = arguments[2] === undefined ? 0 : arguments[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (n < 2) {
 | 
				
			||||||
 | 
					    return { arr: arr, index: index };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var d = arr.reduce(function (a, b, i) {
 | 
				
			||||||
 | 
					    if (Array.isArray(b)) {
 | 
				
			||||||
 | 
					      var _deep2 = deep(b, n - 1, i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var _arr = _deep2.arr;
 | 
				
			||||||
 | 
					      var x = _deep2.index;
 | 
				
			||||||
 | 
					      var merged = a.concat(_arr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      index = x;
 | 
				
			||||||
 | 
					      return merged;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return a;
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { arr: d, index: index };
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.deep = deep;
 | 
				
			||||||
 | 
					var diveTo = (function (_diveTo) {
 | 
				
			||||||
 | 
					  function diveTo(_x4, _x5, _x6) {
 | 
				
			||||||
 | 
					    return _diveTo.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  diveTo.toString = function () {
 | 
				
			||||||
 | 
					    return _diveTo.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return diveTo;
 | 
				
			||||||
 | 
					})(function (arr, indexes, replace) {
 | 
				
			||||||
 | 
					  var answer = [];
 | 
				
			||||||
 | 
					  if (indexes.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    var _iteratorNormalCompletion = true;
 | 
				
			||||||
 | 
					    var _didIteratorError = false;
 | 
				
			||||||
 | 
					    var _iteratorError = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      for (var _iterator = indexes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
 | 
				
			||||||
 | 
					        var index = _step.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        answer.push(diveTo(arr, index, replace));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					      _didIteratorError = true;
 | 
				
			||||||
 | 
					      _iteratorError = err;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        if (!_iteratorNormalCompletion && _iterator['return']) {
 | 
				
			||||||
 | 
					          _iterator['return']();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } finally {
 | 
				
			||||||
 | 
					        if (_didIteratorError) {
 | 
				
			||||||
 | 
					          throw _iteratorError;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    arr[indexes[0]] = replace;
 | 
				
			||||||
 | 
					    return replace;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return answer;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.diveTo = diveTo;
 | 
				
			||||||
 | 
					var flatten = (function (_flatten) {
 | 
				
			||||||
 | 
					  function flatten(_x7) {
 | 
				
			||||||
 | 
					    return _flatten.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  flatten.toString = function () {
 | 
				
			||||||
 | 
					    return _flatten.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return flatten;
 | 
				
			||||||
 | 
					})(function (arr) {
 | 
				
			||||||
 | 
					  if (!Array.isArray(arr) || !arr.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    return arr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return arr.reduce(function (a, b) {
 | 
				
			||||||
 | 
					    return a.concat(flatten(b));
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports.flatten = flatten;
 | 
				
			||||||
 | 
					var removeSymbols = function removeSymbols(string) {
 | 
				
			||||||
 | 
					  return string.replace(/\W/g, '');
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					exports.removeSymbols = removeSymbols;
 | 
				
			||||||
							
								
								
									
										396
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										396
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,396 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _slicedToArray = function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(exports, '__esModule', {
 | 
				
			||||||
 | 
					  value: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ReadStream = require('./readstream');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ReadStream2 = _interopRequireWildcard(_ReadStream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _operators = require('./operators');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _operators2 = _interopRequireWildcard(_operators);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _constants = require('./constats');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _constants2 = _interopRequireWildcard(_constants);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _import = require('./helpers');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ = _interopRequireWildcard(_import);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Mathstring = {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					    * Solves the given math expression, following these steps:
 | 
				
			||||||
 | 
					    * 1. Replace constants in the expression
 | 
				
			||||||
 | 
					    * 2. parse the expression, separating numbers and operators into
 | 
				
			||||||
 | 
					    *    an array
 | 
				
			||||||
 | 
					    * 3. Sort the stack by operators' precedence, it actually groups the
 | 
				
			||||||
 | 
					    *    operator with it's arguments n-level deep
 | 
				
			||||||
 | 
					    * 4. Apply parseFloat to numbers of the array
 | 
				
			||||||
 | 
					    * 5. Solve groups recursively
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {String} expression
 | 
				
			||||||
 | 
					    *        The math expression to solve
 | 
				
			||||||
 | 
					    * @return {Number}
 | 
				
			||||||
 | 
					    *         Result of the expression
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					  solve: function solve(expression) {
 | 
				
			||||||
 | 
					    // replace constants with their values
 | 
				
			||||||
 | 
					    expression = replaceConstants(expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var stack = parseExpression(expression);
 | 
				
			||||||
 | 
					    stack = sortStack(stack);
 | 
				
			||||||
 | 
					    stack = _.parseNumbers(stack);
 | 
				
			||||||
 | 
					    stack = solveStack(stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return stack;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					    * Creates an equation function which replaces variables
 | 
				
			||||||
 | 
					    * in the given expression with the values specified in order,
 | 
				
			||||||
 | 
					    * and solves the new expression
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * Example:
 | 
				
			||||||
 | 
					    *   equation('x+y+z')(2, 5, 6) => solve('2+5+6')
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {String} expression
 | 
				
			||||||
 | 
					    *        The expression to create an equation for (containing variables)
 | 
				
			||||||
 | 
					    * @return {Function}
 | 
				
			||||||
 | 
					    *         The function which replaces variables with values in order
 | 
				
			||||||
 | 
					    *         and solves the expression
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					  equation: function equation(expression) {
 | 
				
			||||||
 | 
					    var stack = parseExpression(expression);
 | 
				
			||||||
 | 
					    var variables = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    stack.forEach(function (a) {
 | 
				
			||||||
 | 
					      if (!_.isNumber(a) && !_operators2['default'][a] && a === a.toLowerCase()) {
 | 
				
			||||||
 | 
					        // grouped variables like (y) need to have their parantheses removed
 | 
				
			||||||
 | 
					        variables.push(_.removeSymbols(a));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return function () {
 | 
				
			||||||
 | 
					      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
 | 
				
			||||||
 | 
					        args[_key] = arguments[_key];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      expression = expression.replace(/[a-z]*/g, function (a) {
 | 
				
			||||||
 | 
					        var index = variables.indexOf(a);
 | 
				
			||||||
 | 
					        if (index > -1) {
 | 
				
			||||||
 | 
					          return args[index] || 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return a;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      console.log(variables, expression);
 | 
				
			||||||
 | 
					      return Mathstring.solve(expression);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var solveStack = (function (_solveStack) {
 | 
				
			||||||
 | 
					  function solveStack(_x) {
 | 
				
			||||||
 | 
					    return _solveStack.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  solveStack.toString = function () {
 | 
				
			||||||
 | 
					    return _solveStack.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return solveStack;
 | 
				
			||||||
 | 
					})(function (stack) {
 | 
				
			||||||
 | 
					  // $0(stack);
 | 
				
			||||||
 | 
					  if (stack.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    stack = stack.map(function (group) {
 | 
				
			||||||
 | 
					      if (!Array.isArray(group)) {
 | 
				
			||||||
 | 
					        return group;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return solveStack(group);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return solveStack(stack);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    return evaluate(stack);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var PRECEDENCES = Object.keys(_operators2['default']).map(function (key) {
 | 
				
			||||||
 | 
					  return _operators2['default'][key].precedence;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var MAX_PRECEDENCE = Math.max.apply(Math, _toConsumableArray(PRECEDENCES));
 | 
				
			||||||
 | 
					var MIN_PRECEDENCE = Math.min.apply(Math, _toConsumableArray(PRECEDENCES));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Parses the given expression into an array of separated
 | 
				
			||||||
 | 
					  * numbers and operators/functions.
 | 
				
			||||||
 | 
					  * The result is passed to parseGroups
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String} expression
 | 
				
			||||||
 | 
					  *        The expression to parse
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         The parsed array
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var parseExpression = function parseExpression(expression) {
 | 
				
			||||||
 | 
					  var stream = new _ReadStream2['default'](expression),
 | 
				
			||||||
 | 
					      stack = [],
 | 
				
			||||||
 | 
					      record = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create an array of separated numbers & operators
 | 
				
			||||||
 | 
					  while (stream.next()) {
 | 
				
			||||||
 | 
					    var cur = stream.current();
 | 
				
			||||||
 | 
					    if (cur === ' ') {
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // it's probably a function with a length more than one
 | 
				
			||||||
 | 
					    if (!_.isNumber(cur) && !_operators2['default'][cur] && cur !== '.') {
 | 
				
			||||||
 | 
					      record += cur;
 | 
				
			||||||
 | 
					    } else if (record.length) {
 | 
				
			||||||
 | 
					      stack.push(record, cur);
 | 
				
			||||||
 | 
					      record = '';
 | 
				
			||||||
 | 
					    } else if (_.isNumber(stack[stack.length - 1]) && (_.isNumber(cur) || cur === '.')) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      stack[stack.length - 1] += cur;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      stack.push(cur);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (record.length) {
 | 
				
			||||||
 | 
					    stack.push(record);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // $0(stack);
 | 
				
			||||||
 | 
					  return parseGroups(stack);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Takes the parsed array from parseExpression and
 | 
				
			||||||
 | 
					  * groups up expressions in parantheses in deep arrays
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Example: 2+(5+4) becomes [2, [5, '+', 4]]
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        The parsed expression
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         Grouped up expression
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var parseGroups = function parseGroups(stack) {
 | 
				
			||||||
 | 
					  // Parantheses become inner arrays which will then be processed first
 | 
				
			||||||
 | 
					  var sub = 0;
 | 
				
			||||||
 | 
					  return stack.reduce(function (a, b) {
 | 
				
			||||||
 | 
					    if (b[b.length - 1] === '(') {
 | 
				
			||||||
 | 
					      if (b.length > 1) {
 | 
				
			||||||
 | 
					        _.dive(a, sub).push(b.slice(0, -1), []);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        _.dive(a, sub).push([]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      sub++;
 | 
				
			||||||
 | 
					    } else if (b === ')') {
 | 
				
			||||||
 | 
					      sub--;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      _.dive(a, sub).push(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return a;
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Gives information about an operator's format
 | 
				
			||||||
 | 
					  * including number of left and right arguments
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String/Object} operator
 | 
				
			||||||
 | 
					  *        The operator object or operator name (e.g. +, -)
 | 
				
			||||||
 | 
					  * @return {Object}
 | 
				
			||||||
 | 
					  *         An object including the count of left and right arguments
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var formatInfo = function formatInfo(operator) {
 | 
				
			||||||
 | 
					  var op = typeof operator === 'string' ? _operators2['default'][operator] : operator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!op) {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var format = op.format.split('1'),
 | 
				
			||||||
 | 
					      left = format[0].length,
 | 
				
			||||||
 | 
					      right = format[1].length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { left: left, right: right };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Groups up operators and their arguments based on their precedence
 | 
				
			||||||
 | 
					  * in deep arrays, the higher the priority, the deeper the group.
 | 
				
			||||||
 | 
					  * This simplifies the evaluating process, the only thing to do is to
 | 
				
			||||||
 | 
					  * evaluate from bottom up, evaluating deep groups first
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        The parsed and grouped expression
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         Grouped expression based on precedences
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var sortStack = (function (_sortStack) {
 | 
				
			||||||
 | 
					  function sortStack(_x2) {
 | 
				
			||||||
 | 
					    return _sortStack.apply(this, arguments);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sortStack.toString = function () {
 | 
				
			||||||
 | 
					    return _sortStack.toString();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return sortStack;
 | 
				
			||||||
 | 
					})(function (stack) {
 | 
				
			||||||
 | 
					  var _iteratorNormalCompletion = true;
 | 
				
			||||||
 | 
					  var _didIteratorError = false;
 | 
				
			||||||
 | 
					  var _iteratorError = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    for (var _iterator = stack.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
 | 
				
			||||||
 | 
					      var _step$value = _slicedToArray(_step.value, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var index = _step$value[0];
 | 
				
			||||||
 | 
					      var item = _step$value[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (Array.isArray(item)) {
 | 
				
			||||||
 | 
					        stack.splice(index, 1, sortStack(item));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (err) {
 | 
				
			||||||
 | 
					    _didIteratorError = true;
 | 
				
			||||||
 | 
					    _iteratorError = err;
 | 
				
			||||||
 | 
					  } finally {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if (!_iteratorNormalCompletion && _iterator['return']) {
 | 
				
			||||||
 | 
					        _iterator['return']();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      if (_didIteratorError) {
 | 
				
			||||||
 | 
					        throw _iteratorError;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (var i = MIN_PRECEDENCE; i <= MAX_PRECEDENCE; i++) {
 | 
				
			||||||
 | 
					    for (var index = 0; index < stack.length; ++index) {
 | 
				
			||||||
 | 
					      var item = stack[index];
 | 
				
			||||||
 | 
					      var op = _operators2['default'][item];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!op || op.precedence !== i) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var _formatInfo = formatInfo(op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var left = _formatInfo.left;
 | 
				
			||||||
 | 
					      var right = _formatInfo.right;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var group = stack.splice(index - left, left + right + 1, []);
 | 
				
			||||||
 | 
					      stack[index - left] = group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (var y = 0; y < i; y++) {
 | 
				
			||||||
 | 
					        group = [group];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      index -= right;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return stack;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Evaluates the given math expression.
 | 
				
			||||||
 | 
					  * The expression is an array with an operator and arguments
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Example: evaluate([2, '+', 4]) == 6
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        A single math expression
 | 
				
			||||||
 | 
					  * @return {Number}
 | 
				
			||||||
 | 
					  *         Result of the expression
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var evaluate = function evaluate(stack) {
 | 
				
			||||||
 | 
					  var _operators$op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var op = findOperator(stack);
 | 
				
			||||||
 | 
					  if (!op) {
 | 
				
			||||||
 | 
					    return stack[0];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var _formatInfo2 = formatInfo(op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var left = _formatInfo2.left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var leftArguments = stack.slice(0, left),
 | 
				
			||||||
 | 
					      rightArguments = stack.slice(left + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (_operators$op = _operators2['default'][op]).fn.apply(_operators$op, _toConsumableArray(leftArguments).concat(_toConsumableArray(rightArguments)));
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Finds the first operator in an array and returns it
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} arr
 | 
				
			||||||
 | 
					  *        The array to look for an operator in
 | 
				
			||||||
 | 
					  * @return {Object}
 | 
				
			||||||
 | 
					  *         The operator object or null if no operator is found
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var findOperator = function findOperator(arr) {
 | 
				
			||||||
 | 
					  var _iteratorNormalCompletion2 = true;
 | 
				
			||||||
 | 
					  var _didIteratorError2 = false;
 | 
				
			||||||
 | 
					  var _iteratorError2 = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    for (var _iterator2 = arr[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
 | 
				
			||||||
 | 
					      var o = _step2.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (typeof o === 'string') {
 | 
				
			||||||
 | 
					        return o;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (err) {
 | 
				
			||||||
 | 
					    _didIteratorError2 = true;
 | 
				
			||||||
 | 
					    _iteratorError2 = err;
 | 
				
			||||||
 | 
					  } finally {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if (!_iteratorNormalCompletion2 && _iterator2['return']) {
 | 
				
			||||||
 | 
					        _iterator2['return']();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      if (_didIteratorError2) {
 | 
				
			||||||
 | 
					        throw _iteratorError2;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return null;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Replaces constants in a string with their values
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String} expression
 | 
				
			||||||
 | 
					  *        The expression to replace constants in
 | 
				
			||||||
 | 
					  * @return {String}
 | 
				
			||||||
 | 
					  *         The expression with constants replaced
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					var replaceConstants = function replaceConstants(expression) {
 | 
				
			||||||
 | 
					  return expression.replace(/[A-Z]*/g, function (a) {
 | 
				
			||||||
 | 
					    var c = _constants2['default'][a];
 | 
				
			||||||
 | 
					    if (!c) {
 | 
				
			||||||
 | 
					      return a;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return typeof c === 'function' ? c() : c;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports['default'] = Mathstring;
 | 
				
			||||||
 | 
					module.exports = exports['default'];
 | 
				
			||||||
							
								
								
									
										114
									
								
								dist/operators.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								dist/operators.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(exports, '__esModule', {
 | 
				
			||||||
 | 
					  value: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Operators and Functions
 | 
				
			||||||
 | 
					 * fn: function used to evaluate value
 | 
				
			||||||
 | 
					 * format: the format using which arguments are parsed:
 | 
				
			||||||
 | 
					 *         0 indicates an argument and 1 indicates the operator
 | 
				
			||||||
 | 
					 *         e.g: factorial is 01, add is 010, like 2!, 2+2
 | 
				
			||||||
 | 
					 * precedence: determines which operators should be evaluated first
 | 
				
			||||||
 | 
					 *             the lower the value, the higher the precedence
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					exports['default'] = {
 | 
				
			||||||
 | 
					  '^': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return Math.pow(a, b);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 0
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '*': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return a * b;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '/': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return a / b;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '%': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return a % b;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '\\': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return Math.floor(a / b);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '+': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return a + b;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '-': {
 | 
				
			||||||
 | 
					    fn: function fn(a, b) {
 | 
				
			||||||
 | 
					      return a - b;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '!': {
 | 
				
			||||||
 | 
					    fn: function fn(a) {
 | 
				
			||||||
 | 
					      var sum = 1;
 | 
				
			||||||
 | 
					      for (var i = 0; i < a; ++i) {
 | 
				
			||||||
 | 
					        sum *= i;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return sum;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '01',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  log: {
 | 
				
			||||||
 | 
					    fn: Math.log,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  ln: {
 | 
				
			||||||
 | 
					    fn: Math.log,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  lg: {
 | 
				
			||||||
 | 
					    fn: function fn(a) {
 | 
				
			||||||
 | 
					      return Math.log(a) / Math.log(2);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  sin: {
 | 
				
			||||||
 | 
					    fn: Math.sin,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  cos: {
 | 
				
			||||||
 | 
					    fn: Math.cos,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  tan: {
 | 
				
			||||||
 | 
					    fn: Math.tan,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  cot: {
 | 
				
			||||||
 | 
					    fn: Math.cot,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					module.exports = exports['default'];
 | 
				
			||||||
							
								
								
									
										61
									
								
								dist/readstream.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								dist/readstream.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Object.defineProperty(exports, '__esModule', {
 | 
				
			||||||
 | 
					  value: true
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports['default'] = function (string) {
 | 
				
			||||||
 | 
					  var i = 0,
 | 
				
			||||||
 | 
					      buffer = [];
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    next: function next() {
 | 
				
			||||||
 | 
					      buffer.push(string[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (i >= string.length) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					      }return string[i++];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    current: function current() {
 | 
				
			||||||
 | 
					      return string[i - 1];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    index: function index() {
 | 
				
			||||||
 | 
					      return i - 1;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    to: function to(n) {
 | 
				
			||||||
 | 
					      var temp = '';
 | 
				
			||||||
 | 
					      var dest = i + n;
 | 
				
			||||||
 | 
					      for (i = i; i < dest; ++i) {
 | 
				
			||||||
 | 
					        temp += [string[i]];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return temp;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    drain: function drain() {
 | 
				
			||||||
 | 
					      return buffer.splice(0, buffer.length);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    replace: (function (_replace) {
 | 
				
			||||||
 | 
					      function replace(_x, _x2, _x3) {
 | 
				
			||||||
 | 
					        return _replace.apply(this, arguments);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      replace.toString = function () {
 | 
				
			||||||
 | 
					        return _replace.toString();
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return replace;
 | 
				
			||||||
 | 
					    })(function (start, end, replace) {
 | 
				
			||||||
 | 
					      var temp = string.split('');
 | 
				
			||||||
 | 
					      temp.splice(start, end, replace);
 | 
				
			||||||
 | 
					      string = temp.join('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      i = i - (end - start);
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					    go: function go(n) {
 | 
				
			||||||
 | 
					      i += n;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    all: function all() {
 | 
				
			||||||
 | 
					      return string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = exports['default'];
 | 
				
			||||||
							
								
								
									
										73
									
								
								dist/tests/basic.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								dist/tests/basic.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _expect = require('chai');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M = require('../index.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M2 = _interopRequireWildcard(_M);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Basic math operators', function () {
 | 
				
			||||||
 | 
					  it('should work for add +', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+2')).to.equal(4);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for minus -', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('15-3')).to.equal(12);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for divison /', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('20/2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multiplication *', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('6*3')).to.equal(18);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for power ^', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('5^2')).to.equal(25);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multi-digit numbers', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('12+15')).to.equal(27);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Precedence', function () {
 | 
				
			||||||
 | 
					  it('Test case 1', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+(2+1)*(1+1)^2')).to.equal(14);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 2', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+5*4/2-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 3', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+(5*4/2)-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 4', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('(2+2)^2+(5+1)*4+(2+(4/2)/2)')).to.equal(16 + 24 + 3);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Functions', function () {
 | 
				
			||||||
 | 
					  it('should work for with parantheses', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('lg(4) * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for without parantheses', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('lg4 * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Constats', function () {
 | 
				
			||||||
 | 
					  it('should work for constant values', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('sin(PI/2)')).to.equal(1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for functions as constants', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('RAND')).to.not.equal(_M2['default'].solve('RAND'));
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										37
									
								
								dist/tests/equation.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								dist/tests/equation.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _expect = require('chai');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M = require('../index.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M2 = _interopRequireWildcard(_M);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Equations', function () {
 | 
				
			||||||
 | 
					  it('should work with one variable', function () {
 | 
				
			||||||
 | 
					    var equation = _M2['default'].equation('x+2');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _expect.expect(equation(2)).to.equal(4);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work with multiple variables', function () {
 | 
				
			||||||
 | 
					    var equation = _M2['default'].equation('x+y');
 | 
				
			||||||
 | 
					    _expect.expect(equation(2, 4)).to.equal(6);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work with multiple instances of the same variable', function () {
 | 
				
			||||||
 | 
					    var equation = _M2['default'].equation('x*x');
 | 
				
			||||||
 | 
					    _expect.expect(equation(4)).to.equal(16);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should only accept lowercase letters', function () {
 | 
				
			||||||
 | 
					    var equation = _M2['default'].equation('X+2');
 | 
				
			||||||
 | 
					    _expect.expect(equation).to['throw']();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case', function () {
 | 
				
			||||||
 | 
					    var equation = _M2['default'].equation('2+x*(y+4)+z^2');
 | 
				
			||||||
 | 
					    _expect.expect(equation(2, 4, 3)).to.equal(27);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										73
									
								
								dist/tests/solve.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								dist/tests/solve.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _expect = require('chai');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M = require('../index.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _M2 = _interopRequireWildcard(_M);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Basic math operators', function () {
 | 
				
			||||||
 | 
					  it('should work for add +', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+2')).to.equal(4);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for minus -', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('15-3')).to.equal(12);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for divison /', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('20/2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multiplication *', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('6*3')).to.equal(18);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for power ^', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('5^2')).to.equal(25);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multi-digit numbers', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('12+15')).to.equal(27);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Precedence', function () {
 | 
				
			||||||
 | 
					  it('Test case 1', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+(2+1)*(1+1)^2')).to.equal(14);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 2', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+5*4/2-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 3', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('2+(5*4/2)-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 4', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('(2+2)^2+(5+1)*4+(2+(4/2)/2)')).to.equal(16 + 24 + 3);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Functions', function () {
 | 
				
			||||||
 | 
					  it('should work for with parantheses', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('lg(4) * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for without parantheses', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('lg4 * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Constats', function () {
 | 
				
			||||||
 | 
					  it('should work for constant values', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('sin(PI/2)')).to.equal(1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for functions as constants', function () {
 | 
				
			||||||
 | 
					    _expect.expect(_M2['default'].solve('RAND')).to.not.equal(_M2['default'].solve('RAND'));
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										78
									
								
								helpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								helpers.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					export const parseFormat = function(a) {
 | 
				
			||||||
 | 
					  const split = a.split('1');
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    left: split[0].length,
 | 
				
			||||||
 | 
					    right: split[1].length
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const isNumber = a => {
 | 
				
			||||||
 | 
					  return !isNaN(+a);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const parseNumbers = (a) => {
 | 
				
			||||||
 | 
					  return a.map(b => {
 | 
				
			||||||
 | 
					    if (isNumber(b)) {
 | 
				
			||||||
 | 
					      return parseFloat(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (Array.isArray(b)) {
 | 
				
			||||||
 | 
					      return parseNumbers(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return b;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const dive = (arr, n) => {
 | 
				
			||||||
 | 
					  let result = arr;
 | 
				
			||||||
 | 
					  for (let i = 0; i < n; ++i) {
 | 
				
			||||||
 | 
					    result = result[result.length - 1];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const deep = (arr, n, index = 0) => {
 | 
				
			||||||
 | 
					  if (n < 2) {
 | 
				
			||||||
 | 
					    return {arr, index};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let d = arr.reduce((a, b, i) => {
 | 
				
			||||||
 | 
					    if (Array.isArray(b)) {
 | 
				
			||||||
 | 
					      let {arr, index: x} = deep(b, n - 1, i),
 | 
				
			||||||
 | 
					          merged = a.concat(arr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      index = x;
 | 
				
			||||||
 | 
					      return merged;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return a;
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {arr: d, index};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const diveTo = (arr, indexes, replace) => {
 | 
				
			||||||
 | 
					  let answer = [];
 | 
				
			||||||
 | 
					  if (indexes.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    for (let index of indexes) {
 | 
				
			||||||
 | 
					      answer.push(diveTo(arr, index, replace));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    arr[indexes[0]] = replace;
 | 
				
			||||||
 | 
					    return replace;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return answer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const flatten = (arr) => {
 | 
				
			||||||
 | 
					  if (!Array.isArray(arr) || !arr.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    return arr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return arr.reduce((a, b) => {
 | 
				
			||||||
 | 
					    return a.concat(flatten(b));
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const removeSymbols = string => {
 | 
				
			||||||
 | 
					  return string.replace(/\W/g, '');
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										296
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,296 @@
 | 
				
			|||||||
 | 
					import ReadStream from './readstream';
 | 
				
			||||||
 | 
					import operators from './operators';
 | 
				
			||||||
 | 
					import constants from './constats';
 | 
				
			||||||
 | 
					import * as _ from './helpers';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let Mathstring = {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					    * Solves the given math expression, following these steps:
 | 
				
			||||||
 | 
					    * 1. Replace constants in the expression
 | 
				
			||||||
 | 
					    * 2. parse the expression, separating numbers and operators into
 | 
				
			||||||
 | 
					    *    an array
 | 
				
			||||||
 | 
					    * 3. Sort the stack by operators' precedence, it actually groups the
 | 
				
			||||||
 | 
					    *    operator with it's arguments n-level deep
 | 
				
			||||||
 | 
					    * 4. Apply parseFloat to numbers of the array
 | 
				
			||||||
 | 
					    * 5. Solve groups recursively
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {String} expression
 | 
				
			||||||
 | 
					    *        The math expression to solve
 | 
				
			||||||
 | 
					    * @return {Number}
 | 
				
			||||||
 | 
					    *         Result of the expression
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					  solve(expression) {
 | 
				
			||||||
 | 
					    // replace constants with their values
 | 
				
			||||||
 | 
					    expression = replaceConstants(expression);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let stack = parseExpression(expression);
 | 
				
			||||||
 | 
					    stack = sortStack(stack);
 | 
				
			||||||
 | 
					    stack = _.parseNumbers(stack);
 | 
				
			||||||
 | 
					    stack = solveStack(stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return stack;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					    * Creates an equation function which replaces variables
 | 
				
			||||||
 | 
					    * in the given expression with the values specified in order,
 | 
				
			||||||
 | 
					    * and solves the new expression
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * Example:
 | 
				
			||||||
 | 
					    *   equation('x+y+z')(2, 5, 6) => solve('2+5+6')
 | 
				
			||||||
 | 
					    *
 | 
				
			||||||
 | 
					    * @param {String} expression
 | 
				
			||||||
 | 
					    *        The expression to create an equation for (containing variables)
 | 
				
			||||||
 | 
					    * @return {Function}
 | 
				
			||||||
 | 
					    *         The function which replaces variables with values in order
 | 
				
			||||||
 | 
					    *         and solves the expression
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
 | 
					  equation(expression) {
 | 
				
			||||||
 | 
					    let stack = parseExpression(expression);
 | 
				
			||||||
 | 
					    let variables = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    stack.forEach(a => {
 | 
				
			||||||
 | 
					      if (!_.isNumber(a) && !operators[a] && a === a.toLowerCase()) {
 | 
				
			||||||
 | 
					        // grouped variables like (y) need to have their parantheses removed
 | 
				
			||||||
 | 
					        variables.push(_.removeSymbols(a));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return function(...args) {
 | 
				
			||||||
 | 
					      expression = expression.replace(/[a-z]*/g, a => {
 | 
				
			||||||
 | 
					        let index = variables.indexOf(a);
 | 
				
			||||||
 | 
					        if (index > -1) {
 | 
				
			||||||
 | 
					          return args[index] || 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return a;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      console.log(variables, expression);
 | 
				
			||||||
 | 
					      return Mathstring.solve(expression);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const solveStack = stack => {
 | 
				
			||||||
 | 
					  // $0(stack);
 | 
				
			||||||
 | 
					  if (stack.some(Array.isArray)) {
 | 
				
			||||||
 | 
					    stack = stack.map(group => {
 | 
				
			||||||
 | 
					      if (!Array.isArray(group)) {
 | 
				
			||||||
 | 
					        return group;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return solveStack(group);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return solveStack(stack);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    return evaluate(stack);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PRECEDENCES = Object.keys(operators).map(key => {
 | 
				
			||||||
 | 
					  return operators[key].precedence;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MAX_PRECEDENCE = Math.max(...PRECEDENCES);
 | 
				
			||||||
 | 
					const MIN_PRECEDENCE = Math.min(...PRECEDENCES);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Parses the given expression into an array of separated
 | 
				
			||||||
 | 
					  * numbers and operators/functions.
 | 
				
			||||||
 | 
					  * The result is passed to parseGroups
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String} expression
 | 
				
			||||||
 | 
					  *        The expression to parse
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         The parsed array
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const parseExpression = expression => {
 | 
				
			||||||
 | 
					  let stream = new ReadStream(expression),
 | 
				
			||||||
 | 
					      stack = [],
 | 
				
			||||||
 | 
					      record = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Create an array of separated numbers & operators
 | 
				
			||||||
 | 
					  while (stream.next()) {
 | 
				
			||||||
 | 
					    const cur = stream.current();
 | 
				
			||||||
 | 
					    if (cur === ' ') {
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // it's probably a function with a length more than one
 | 
				
			||||||
 | 
					    if (!_.isNumber(cur) && !operators[cur] && cur !== '.') {
 | 
				
			||||||
 | 
					      record += cur;
 | 
				
			||||||
 | 
					    } else if (record.length) {
 | 
				
			||||||
 | 
					      stack.push(record, cur);
 | 
				
			||||||
 | 
					      record = '';
 | 
				
			||||||
 | 
					    } else if (_.isNumber(stack[stack.length - 1]) &&
 | 
				
			||||||
 | 
					              (_.isNumber(cur) || cur === '.')) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      stack[stack.length - 1] += cur;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      stack.push(cur);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (record.length) {
 | 
				
			||||||
 | 
					    stack.push(record);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // $0(stack);
 | 
				
			||||||
 | 
					  return parseGroups(stack);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Takes the parsed array from parseExpression and
 | 
				
			||||||
 | 
					  * groups up expressions in parantheses in deep arrays
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Example: 2+(5+4) becomes [2, [5, '+', 4]]
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        The parsed expression
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         Grouped up expression
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const parseGroups = stack => {
 | 
				
			||||||
 | 
					  // Parantheses become inner arrays which will then be processed first
 | 
				
			||||||
 | 
					  let sub = 0;
 | 
				
			||||||
 | 
					  return stack.reduce((a, b) => {
 | 
				
			||||||
 | 
					    if (b[b.length - 1] === '(') {
 | 
				
			||||||
 | 
					      if (b.length > 1) {
 | 
				
			||||||
 | 
					        _.dive(a, sub).push(b.slice(0, -1), []);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        _.dive(a, sub).push([]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      sub++;
 | 
				
			||||||
 | 
					    } else if (b === ')') {
 | 
				
			||||||
 | 
					      sub--;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      _.dive(a, sub).push(b);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return a;
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Gives information about an operator's format
 | 
				
			||||||
 | 
					  * including number of left and right arguments
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String/Object} operator
 | 
				
			||||||
 | 
					  *        The operator object or operator name (e.g. +, -)
 | 
				
			||||||
 | 
					  * @return {Object}
 | 
				
			||||||
 | 
					  *         An object including the count of left and right arguments
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const formatInfo = operator => {
 | 
				
			||||||
 | 
					  let op = typeof operator === 'string' ? operators[operator]
 | 
				
			||||||
 | 
					                                        : operator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!op) {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const format = op.format.split('1'),
 | 
				
			||||||
 | 
					        left = format[0].length,
 | 
				
			||||||
 | 
					        right = format[1].length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { left, right };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Groups up operators and their arguments based on their precedence
 | 
				
			||||||
 | 
					  * in deep arrays, the higher the priority, the deeper the group.
 | 
				
			||||||
 | 
					  * This simplifies the evaluating process, the only thing to do is to
 | 
				
			||||||
 | 
					  * evaluate from bottom up, evaluating deep groups first
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        The parsed and grouped expression
 | 
				
			||||||
 | 
					  * @return {Array}
 | 
				
			||||||
 | 
					  *         Grouped expression based on precedences
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const sortStack = stack => {
 | 
				
			||||||
 | 
					  for (let [index, item] of stack.entries()) {
 | 
				
			||||||
 | 
					    if (Array.isArray(item)) {
 | 
				
			||||||
 | 
					      stack.splice(index, 1, sortStack(item));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (let i = MIN_PRECEDENCE; i <= MAX_PRECEDENCE; i++) {
 | 
				
			||||||
 | 
					    for (let index = 0; index < stack.length; ++index) {
 | 
				
			||||||
 | 
					      let item = stack[index];
 | 
				
			||||||
 | 
					      let op = operators[item];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!op || op.precedence !== i) {
 | 
				
			||||||
 | 
					        continue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const { left, right } = formatInfo(op);
 | 
				
			||||||
 | 
					      let group = stack.splice(index - left, left + right + 1, []);
 | 
				
			||||||
 | 
					      stack[index - left] = group;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for (let y = 0; y < i; y++) {
 | 
				
			||||||
 | 
					        group = [group];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      index -= right;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return stack;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Evaluates the given math expression.
 | 
				
			||||||
 | 
					  * The expression is an array with an operator and arguments
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Example: evaluate([2, '+', 4]) == 6
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} stack
 | 
				
			||||||
 | 
					  *        A single math expression
 | 
				
			||||||
 | 
					  * @return {Number}
 | 
				
			||||||
 | 
					  *         Result of the expression
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const evaluate = stack => {
 | 
				
			||||||
 | 
					  const op = findOperator(stack);
 | 
				
			||||||
 | 
					  if (!op) {
 | 
				
			||||||
 | 
					    return stack[0];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  const { left } = formatInfo(op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let leftArguments = stack.slice(0, left),
 | 
				
			||||||
 | 
					      rightArguments = stack.slice(left + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return operators[op].fn(...leftArguments, ...rightArguments);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Finds the first operator in an array and returns it
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {Array} arr
 | 
				
			||||||
 | 
					  *        The array to look for an operator in
 | 
				
			||||||
 | 
					  * @return {Object}
 | 
				
			||||||
 | 
					  *         The operator object or null if no operator is found
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const findOperator = arr => {
 | 
				
			||||||
 | 
					  for (let o of arr) {
 | 
				
			||||||
 | 
					    if (typeof o === 'string') {
 | 
				
			||||||
 | 
					      return o;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return null;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * Replaces constants in a string with their values
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * @param {String} expression
 | 
				
			||||||
 | 
					  *        The expression to replace constants in
 | 
				
			||||||
 | 
					  * @return {String}
 | 
				
			||||||
 | 
					  *         The expression with constants replaced
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const replaceConstants = expression => {
 | 
				
			||||||
 | 
					  return expression.replace(/[A-Z]*/g, (a) => {
 | 
				
			||||||
 | 
					    let c = constants[a];
 | 
				
			||||||
 | 
					    if (!c) {
 | 
				
			||||||
 | 
					      return a;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return typeof c === 'function' ? c() : c;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Mathstring;
 | 
				
			||||||
							
								
								
									
										92
									
								
								operators.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								operators.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Operators and Functions
 | 
				
			||||||
 | 
					 * fn: function used to evaluate value
 | 
				
			||||||
 | 
					 * format: the format using which arguments are parsed:
 | 
				
			||||||
 | 
					 *         0 indicates an argument and 1 indicates the operator
 | 
				
			||||||
 | 
					 *         e.g: factorial is 01, add is 010, like 2!, 2+2
 | 
				
			||||||
 | 
					 * precedence: determines which operators should be evaluated first
 | 
				
			||||||
 | 
					 *             the lower the value, the higher the precedence
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  '^': {
 | 
				
			||||||
 | 
					    fn: (a, b) => Math.pow(a, b),
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 0
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '*': {
 | 
				
			||||||
 | 
					    fn: (a, b) => a * b,
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '/': {
 | 
				
			||||||
 | 
					    fn: (a, b) => a / b,
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '%': {
 | 
				
			||||||
 | 
					    fn: (a, b) => a % b,
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '\\': {
 | 
				
			||||||
 | 
					    fn: (a, b) => Math.floor(a / b),
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '+': {
 | 
				
			||||||
 | 
					    fn: (a, b) => a + b,
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '-': {
 | 
				
			||||||
 | 
					    fn: (a, b) => a - b,
 | 
				
			||||||
 | 
					    format: '010',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  '!': {
 | 
				
			||||||
 | 
					    fn: (a) => {
 | 
				
			||||||
 | 
					      let sum = 1;
 | 
				
			||||||
 | 
					      for (var i = 0; i < a; ++i) {
 | 
				
			||||||
 | 
					        sum *= i;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return sum;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    format: '01',
 | 
				
			||||||
 | 
					    precedence: 2
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'log': {
 | 
				
			||||||
 | 
					    fn: Math.log,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'ln': {
 | 
				
			||||||
 | 
					    fn: Math.log,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'lg': {
 | 
				
			||||||
 | 
					    fn: (a) => Math.log(a) / Math.log(2),
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'sin': {
 | 
				
			||||||
 | 
					    fn: Math.sin,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'cos': {
 | 
				
			||||||
 | 
					    fn: Math.cos,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'tan': {
 | 
				
			||||||
 | 
					    fn: Math.tan,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  'cot': {
 | 
				
			||||||
 | 
					    fn: Math.cot,
 | 
				
			||||||
 | 
					    format: '10',
 | 
				
			||||||
 | 
					    precedence: -1
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										26
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "mathstring",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "main": "dist/index.js",
 | 
				
			||||||
 | 
					  "directories": {
 | 
				
			||||||
 | 
					    "test": "tests"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "test": "grunt test"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "keywords": [
 | 
				
			||||||
 | 
					    "Math",
 | 
				
			||||||
 | 
					    "JavaScript"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "author": "Mahdi Dibaiee",
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "grunt": "^0.4.5",
 | 
				
			||||||
 | 
					    "grunt-babel": "^5.0.0",
 | 
				
			||||||
 | 
					    "grunt-contrib-watch": "^0.6.1",
 | 
				
			||||||
 | 
					    "grunt-eslint": "^11.0.0",
 | 
				
			||||||
 | 
					    "grunt-mocha-test": "^0.12.7",
 | 
				
			||||||
 | 
					    "mocha": "^2.2.4"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										41
									
								
								readstream.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								readstream.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					export default function(string) {
 | 
				
			||||||
 | 
					  let i = 0, buffer = [];
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    next() {
 | 
				
			||||||
 | 
					      buffer.push(string[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (i >= string.length) return null;
 | 
				
			||||||
 | 
					      return string[i++];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    current() {
 | 
				
			||||||
 | 
					      return string[i - 1];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    index() {
 | 
				
			||||||
 | 
					      return i - 1;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    to(n) {
 | 
				
			||||||
 | 
					      let temp = '';
 | 
				
			||||||
 | 
					      const dest = i + n;
 | 
				
			||||||
 | 
					      for (i = i; i < dest; ++i) {
 | 
				
			||||||
 | 
					        temp += [string[i]];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return temp;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    drain() {
 | 
				
			||||||
 | 
					      return buffer.splice(0, buffer.length);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    replace(start, end, replace) {
 | 
				
			||||||
 | 
					      let temp = string.split('');
 | 
				
			||||||
 | 
					      temp.splice(start, end, replace);
 | 
				
			||||||
 | 
					      string = temp.join('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      i = i - (end - start);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    go(n) {
 | 
				
			||||||
 | 
					      i += n;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    all() {
 | 
				
			||||||
 | 
					      return string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								tests/equation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/equation.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import {expect} from 'chai';
 | 
				
			||||||
 | 
					import M from '../index.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Equations', () => {
 | 
				
			||||||
 | 
					  it('should work with one variable', () => {
 | 
				
			||||||
 | 
					    let equation = M.equation('x+2');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    expect(equation(2)).to.equal(4);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work with multiple variables', () => {
 | 
				
			||||||
 | 
					    let equation = M.equation('x+y');
 | 
				
			||||||
 | 
					    expect(equation(2, 4)).to.equal(6);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work with multiple instances of the same variable', () => {
 | 
				
			||||||
 | 
					    let equation = M.equation('x*x');
 | 
				
			||||||
 | 
					    expect(equation(4)).to.equal(16);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should only accept lowercase letters', () => {
 | 
				
			||||||
 | 
					    let equation = M.equation('X+2');
 | 
				
			||||||
 | 
					    expect(equation).to.throw();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case', () => {
 | 
				
			||||||
 | 
					    let equation = M.equation('2+x*(y+4)+z^2');
 | 
				
			||||||
 | 
					    expect(equation(2, 4, 3)).to.equal(27);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										66
									
								
								tests/solve.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								tests/solve.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					import {expect} from 'chai';
 | 
				
			||||||
 | 
					import M from '../index.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Basic math operators', () => {
 | 
				
			||||||
 | 
					  it('should work for add +', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('2+2')).to.equal(4);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for minus -', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('15-3')).to.equal(12);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for divison /', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('20/2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multiplication *', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('6*3')).to.equal(18);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for power ^', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('5^2')).to.equal(25);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for multi-digit numbers', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('12+15')).to.equal(27);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Precedence', () => {
 | 
				
			||||||
 | 
					  it('Test case 1', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('2+(2+1)*(1+1)^2')).to.equal(14);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 2', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('2+5*4/2-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 3', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('2+(5*4/2)-2')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('Test case 4', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('(2+2)^2+(5+1)*4+(2+(4/2)/2)')).to.equal(16 + 24 + 3);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Functions', () => {
 | 
				
			||||||
 | 
					  it('should work for with parantheses', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('lg(4) * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for without parantheses', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('lg4 * 5')).to.equal(10);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('Constats', () => {
 | 
				
			||||||
 | 
					  it('should work for constant values', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('sin(PI/2)')).to.equal(1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should work for functions as constants', () => {
 | 
				
			||||||
 | 
					    expect(M.solve('RAND')).to.not.equal(M.solve('RAND'));
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
		Reference in New Issue
	
	Block a user