Skip to content

Commit

Permalink
Merge pull request #2 from o-p/op/arithmetic
Browse files Browse the repository at this point in the history
Add math operators, rename existing comparison operators.
  • Loading branch information
o-p authored Sep 28, 2020
2 parents 1ccb073 + 0b78da6 commit f9f97db
Show file tree
Hide file tree
Showing 17 changed files with 468 additions and 13 deletions.
18 changes: 9 additions & 9 deletions src/OperatorManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ protected function buildins(): array
'missing_some' => null,
// Logic and Boolean Operations
'if' => null,
'==' => Operators\Equals::class,
'===' => Operators\Same::class,
'!=' => Operators\NotEquals::class,
'!==' => Operators\NotSame::class,
'==' => Operators\Equal::class,
'===' => Operators\Identical::class,
'!=' => Operators\NotEqual::class,
'!==' => Operators\NotIdentical::class,
'!' => Operators\Not::class,
'!!' => Operators\Booleanify::class,
'or' => Operators\OrOperator::class,
Expand All @@ -52,11 +52,11 @@ protected function buildins(): array
'<=' => Operators\LessThanOrEqual::class,
'max' => null,
'min' => null,
'+' => null,
'-' => null,
'*' => null,
'/' => null,
'%' => null,
'+' => Operators\Plus::class,
'-' => Operators\Minus::class,
'*' => Operators\Multiply::class,
'/' => Operators\Divide::class,
'%' => Operators\Modulo::class,
// Array Operations
'map' => null,
'reduce' => null,
Expand Down
25 changes: 25 additions & 0 deletions src/Operators/Divide.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
namespace JsonLogic\Operators;

use Closure;
use JsonLogic\Parameters;

/**
* @operator /
*/
class Divide extends Operator
{
protected $alias = '/';

public function params($param): Closure
{
$this->autoValidateParams($param);
$prepared = Parameters::from($param);

return function (&$data) use (&$prepared) {
return $prepared->reduce(function ($a, $b) {
return $a / $b;
}, $data);
};
}
}
2 changes: 1 addition & 1 deletion src/Operators/Equals.php → src/Operators/Equal.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* @operator ==
*/
class Equals extends Operator
class Equal extends Operator
{
protected $alias = '==';
protected $minParamCounts = 2;
Expand Down
2 changes: 1 addition & 1 deletion src/Operators/Same.php → src/Operators/Identical.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* @operator ===
*/
class Same extends Operator
class Identical extends Operator
{
protected $alias = '===';
protected $minParamCounts = 2;
Expand Down
25 changes: 25 additions & 0 deletions src/Operators/Minus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
namespace JsonLogic\Operators;

use Closure;
use JsonLogic\Parameters;

/**
* @operator -
*/
class Minus extends Operator
{
protected $alias = '-';

public function params($param): Closure
{
$this->autoValidateParams($param);
$prepared = Parameters::from($param);

return function (&$data) use (&$prepared) {
return $prepared->reduce(function ($a, $b) {
return $a - $b;
}, $data);
};
}
}
25 changes: 25 additions & 0 deletions src/Operators/Modulo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
namespace JsonLogic\Operators;

use Closure;
use JsonLogic\Parameters;

/**
* @operator %
*/
class Modulo extends Operator
{
protected $alias = '%';

public function params($param): Closure
{
$this->autoValidateParams($param);
$prepared = Parameters::from($param);

return function (&$data) use (&$prepared) {
return $prepared->reduce(function ($a, $b) {
return $a % $b;
}, $data);
};
}
}
23 changes: 23 additions & 0 deletions src/Operators/Multiply.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
namespace JsonLogic\Operators;

use Closure;
use JsonLogic\Parameters;

/**
* @operator *
*/
class Multiply extends Operator
{
protected $alias = '*';

public function params($param): Closure
{
$this->autoValidateParams($param);
$prepared = Parameters::from($param);

return function (&$data) use (&$prepared) {
return array_product($prepared->values($data));
};
}
}
2 changes: 1 addition & 1 deletion src/Operators/NotEquals.php → src/Operators/NotEqual.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* @operator !=
*/
class NotEquals extends Operator
class NotEqual extends Operator
{
protected $alias = '!=';
protected $minParamCounts = 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* @operator !==
*/
class NotSame extends Operator
class NotIdentical extends Operator
{
protected $alias = '!==';
protected $minParamCounts = 2;
Expand Down
23 changes: 23 additions & 0 deletions src/Operators/Plus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
namespace JsonLogic\Operators;

use Closure;
use JsonLogic\Parameters;

/**
* @operator +
*/
class Plus extends Operator
{
protected $alias = '+';

public function params($param): Closure
{
$this->autoValidateParams($param);
$prepared = Parameters::from($param);

return function (&$data) use (&$prepared) {
return array_sum($prepared->values($data));
};
}
}
22 changes: 22 additions & 0 deletions src/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ public function everyPairs(callable $fn, &$data): bool
);
}

public function reduce(callable $fn, &$data, $init = null)
{
return is_null($init)
? array_reduce(
array_slice($this->params, 1),
function ($curry, $closure) use (&$data, &$fn) {
return $fn($curry, $closure($data));
},
$this->params[0]($data)
)
: array_reduce($this->params, function ($curry, $closure) use (&$data, &$fn) {
return $fn($curry, $closure($data));
}, $init);
}

public function values(&$data): array
{
return array_map(function ($getter) use (&$data) {
return $getter($data);
}, $this->params);
}

private function recurseEvery(callable &$fn, &$data, Closure &$getter = null, Closure &...$rest): bool
{
return $getter
Expand Down
47 changes: 47 additions & 0 deletions tests/JsonLogic/Operators/DivideTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
namespace Tests\JsonLogic\Operators;

use JsonLogic\Operators\Divide;
use Tests\TestCase;

use function number_format;

/**
* @group operators
*/
class DivideTest extends TestCase
{
/** @dataProvider cases */
public function test(array $params, $data, string $expect): void
{
$this->assertSame(
$expect,
number_format((new Divide())->params($params)($data), 3)
);
}

public function cases(): array
{
return [
'1 ÷ 1' => [[1, 1], null, '1.000'],
'3.1415926 ÷ 2.7182818' => [[3.1415926, 2.7182818], null, '1.156'],
'5/7 ÷ 25/49' => [[5/7, 25/49], null, '1.400'],
'1/2 ÷ 3/2 ÷ 4/3 ÷ 5/4' => [[1/2, 3/2, 4/3, 5/4], null, '0.200'],
'Pi ÷ e' => [
[
['var' => 'real.irrational.Pi'],
['var' => 'real.irrational.e'],
],
[
'real' => [
'irrational' => [
'Pi' => 3.1415926,
'e' => 2.7182818,
],
],
],
'1.156',
],
];
}
}
47 changes: 47 additions & 0 deletions tests/JsonLogic/Operators/MinusTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
namespace Tests\JsonLogic\Operators;

use JsonLogic\Operators\Minus;
use Tests\TestCase;

use function number_format;

/**
* @group operators
*/
class MinusTest extends TestCase
{
/** @dataProvider cases */
public function test(array $params, $data, string $expect): void
{
$this->assertSame(
$expect,
number_format((new Minus())->params($params)($data), 2)
);
}

public function cases(): array
{
return [
'1 - 1' => [[1, 1], null, '0.00'],
'3.1415926 - 2.7182818' => [[3.1415926, 2.7182818], null, '0.42'],
'1/3 - 2/3' => [[1/3, 2/3], null, '-0.33'],
'1/2 - 1/3 - 1/4 - 1/5 - 1/6' => [[1/2, 1/3, 1/4, 1/5, 1/6], null, '-0.45'],
'Pi - e' => [
[
['var' => 'real.irrational.Pi'],
['var' => 'real.irrational.e'],
],
[
'real' => [
'irrational' => [
'Pi' => 3.1415926,
'e' => 2.7182818,
],
],
],
'0.42',
],
];
}
}
40 changes: 40 additions & 0 deletions tests/JsonLogic/Operators/ModuloTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
namespace Tests\JsonLogic\Operators;

use JsonLogic\Operators\Modulo;
use Tests\TestCase;

/**
* @group operators
*/
class ModuloTest extends TestCase
{
/** @dataProvider cases */
public function test(array $params, $data, int $expect): void
{
$this->assertSame(
$expect,
(new Modulo())->params($params)($data)
);
}

public function cases(): array
{
return [
'1 % 1' => [[1, 1], null, 0],
'100 % 3' => [[100, 3], null, 1],
'100 % 23 % 17 % 5' => [[100, 23, 17, 5], null, 3],
'100 % 17' => [
[
['var' => 'one hundred'],
['var' => 'seventeen'],
],
[
'one hundred' => 100,
'seventeen' => 17,
],
15,
],
];
}
}
Loading

0 comments on commit f9f97db

Please sign in to comment.