Skip to content

Commit f3c58a5

Browse files
authored
v1.1.0 (#7)
* Use MIT license (#4) * Add getOperands function (#6)
1 parent 128bd4b commit f3c58a5

9 files changed

+175
-57
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Beyond Essential Systems Ptd. Ltd.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+29-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,28 @@
11
# @beyondessential/arithmetic
22

3-
Utility to evaluate [BODMAS](https://en.wikipedia.org/wiki/Order_of_operations) arithmetic formulas. It is an implementation of the [shunting yard algorithm](https://en.wikipedia.org/wiki/Shunting-yard_algorithm).
3+
Utility to evaluate [BODMAS](https://en.wikipedia.org/wiki/Order_of_operations) arithmetic formulas. It is an implementation of the [shunting yard algorithm](https://en.wikipedia.org/wiki/Shunting-yard_algorithm).
44

5-
### Installation
5+
## Installation
66

7-
**Note:** Since this is a private repository, you will need to authenticate your connection to GitHub, for example via [ssh](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh).
7+
With `yarn`:
88

99
```
10-
yarn add beyondessential/arithmetic
10+
yarn add @beyondessential/arithmetic
1111
```
1212

13-
### Usage
13+
With `npm`:
14+
15+
```
16+
npm add @beyondessential/arithmetic
17+
```
18+
19+
## API
20+
21+
`formulaText` must be in [BODMAS](https://en.wikipedia.org/wiki/Order_of_operations) format.
22+
23+
### `runArithmetic(formulaText: string, values?: Record<string, string | number>): number`
24+
25+
Usage example:
1426

1527
```js
1628
import { runArithmetic } from '@beyondessential/arithmetic';
@@ -19,7 +31,18 @@ const value = runArithmetic('(-1 + 2.5) / 3');
1931
console.log(value); // 0.5
2032

2133
const valueWithVariable = runArithmetic('2 * four', {
22-
four: 4
34+
four: 4,
2335
});
2436
console.log(valueWithVariable); // 8
2537
```
38+
39+
### `getOperands(formulaText: string): string[]`
40+
41+
Usage example:
42+
43+
```js
44+
import { getOperands } from '@beyondessential/arithmetic';
45+
46+
const operands = getOperands('(-a * b) / 3');
47+
console.log(operands); // ['a', 'b', '3']
48+
```

__tests__/arithmetic.test.js

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
18
import { runArithmetic } from '../src/arithmetic';
29

310
describe('Arithmetic', () => {

__tests__/symbols.test.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import { getOperands } from '../src/symbols';
9+
10+
describe('getOperands()', () => {
11+
const testData = [
12+
['numbers', '1 + 2', ['1', '2']],
13+
['single letters', 'a + b', ['a', 'b']],
14+
['words', 'alpha + beta', ['alpha', 'beta']],
15+
["'u' letter", 'a + u', ['a', 'u']],
16+
["words containing 'u', 'x'", 'user * experience - ux', ['user', 'experience', 'ux']],
17+
['excessive whitespace', ' a + b ', ['a', 'b']],
18+
['no whitespace', 'a+b', ['a', 'b']],
19+
['same operand multiple times', 'a * b + a', ['a', 'b']],
20+
['all operators', '(a + -b) / ((2 * c) - 3 x d)', ['a', 'b', '2', 'c', '3', 'd']],
21+
];
22+
23+
it.each(testData)('%s', (_, formula, expected) => {
24+
expect(getOperands(formula)).toStrictEqual(expected);
25+
});
26+
});

index.d.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1-
export function runArithmetic(formula: string, values?: Record<string, string | number>): number;
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export function getOperands(formulaText: string): string[];
9+
export function runArithmetic(
10+
formulaText: string,
11+
values?: Record<string, string | number>,
12+
): number;

package.json

+28-21
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,38 @@
11
{
22
"name": "@beyondessential/arithmetic",
3-
"private": true,
43
"version": "1.0.0",
54
"description": "Utility to evaluate BODMAS arithmetic formulas",
5+
"keywords": [
6+
"arithmetic",
7+
"calculations",
8+
"shunting yard",
9+
"bodmas"
10+
],
11+
"homepage": "https://github.com/beyondessential/arithmetic.git#readme",
12+
"bugs": {
13+
"url": "https://github.com/beyondessential/arithmetic/issues"
14+
},
15+
"repository": "[email protected]:beyondessential/arithmetic.git",
16+
"license": "MIT",
17+
"author": "Beyond Essential Systems <[email protected]> (https://beyondessential.com.au)",
618
"main": "dist/index.js",
719
"files": [
820
"src",
921
"index.d.ts"
1022
],
11-
"homepage": "https://github.com/beyondessential/arithmetic.git#readme",
12-
"repository": "[email protected]:beyondessential/arithmetic.git",
1323
"scripts": {
1424
"build": "babel src --out-dir dist --ignore 'src/__tests__/**'",
1525
"postinstall": "yarn build",
1626
"test": "NODE_ENV=test jest",
1727
"test:coverage": "yarn test --coverage",
1828
"test:watch": "yarn test --watch"
1929
},
20-
"keywords": [],
21-
"author": "Beyond Essential Systems Pty. Ltd.",
22-
"license": "AGPL-3.0-only",
23-
"devDependencies": {
24-
"@babel/cli": "^7.10.5",
25-
"@babel/core": "^7.11.1",
26-
"@babel/preset-env": "^7.11.0",
27-
"@beyondessential/eslint-config-beyondessential": "^2.5.0",
28-
"babel-jest": "^26.3.0",
29-
"eslint": "^7.7.0",
30-
"jest": "^26.4.0",
31-
"prettier": "^2.0.5"
30+
"babel": {
31+
"presets": [
32+
[
33+
"@babel/preset-env"
34+
]
35+
]
3236
},
3337
"eslintConfig": {
3438
"extends": "@beyondessential/eslint-config-beyondessential",
@@ -41,11 +45,14 @@
4145
}
4246
]
4347
},
44-
"babel": {
45-
"presets": [
46-
[
47-
"@babel/preset-env"
48-
]
49-
]
48+
"devDependencies": {
49+
"@babel/cli": "^7.10.5",
50+
"@babel/core": "^7.11.1",
51+
"@babel/preset-env": "^7.11.0",
52+
"@beyondessential/eslint-config-beyondessential": "^2.5.0",
53+
"babel-jest": "^26.3.0",
54+
"eslint": "^7.7.0",
55+
"jest": "^26.4.0",
56+
"prettier": "^2.0.5"
5057
}
5158
}

src/arithmetic.js

+8-29
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
18
// This module is responsible for taking a string, interpreting it as an
29
// arithmetic expression, substituting in some provided values,
310
// and then calculating the result of that expression.
@@ -15,35 +22,7 @@
1522
// that, don't sweat! There're unit tests and you can validate that things
1623
// work over there.
1724

18-
function isOperator(token) {
19-
switch (token) {
20-
case '+':
21-
case '-':
22-
case '/':
23-
case '*':
24-
case 'x':
25-
case 'u':
26-
return true;
27-
default:
28-
return false;
29-
}
30-
}
31-
32-
function getPrecedence(operator) {
33-
switch (operator) {
34-
case 'u':
35-
return 4;
36-
case '*':
37-
case 'x':
38-
case '/':
39-
return 3;
40-
case '+':
41-
case '-':
42-
return 2;
43-
default:
44-
throw new Error('Invalid operator');
45-
}
46-
}
25+
import { isOperator, getPrecedence } from './symbols';
4726

4827
const unaryRegex = /(^|[*x/+\-u])-/g;
4928
function replaceUnaryMinus(text) {

src/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
18
export { runArithmetic } from './arithmetic';
9+
export { getOperands } from './symbols';

src/symbols.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Copyright (c) 2020 Beyond Essential Systems Pty Ltd
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export function isOperator(token) {
9+
return ['+', '-', '/', '*', 'x', 'u'].includes(token);
10+
}
11+
12+
export function getPrecedence(operator) {
13+
switch (operator) {
14+
case 'u':
15+
return 4;
16+
case '*':
17+
case 'x':
18+
case '/':
19+
return 3;
20+
case '+':
21+
case '-':
22+
return 2;
23+
default:
24+
throw new Error('Invalid operator');
25+
}
26+
}
27+
28+
export function getOperands(formulaText) {
29+
const operands = formulaText
30+
// Replace the alternate multiplication symbol 'x' with a non-alphanumeric character
31+
.replace(/(^|\W)x(\W|$)/, ' ')
32+
.split(/[+-/*() ]/g)
33+
.filter(c => c !== '');
34+
35+
return [...new Set(operands)];
36+
}

0 commit comments

Comments
 (0)