Skip to content

Commit

Permalink
Add failedConditions attribute for failed event
Browse files Browse the repository at this point in the history
  • Loading branch information
Kenneth Ocastro committed Nov 9, 2024
1 parent 9759947 commit 1370cdf
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 51 deletions.
8 changes: 7 additions & 1 deletion src/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function evaluate(): array
}

$result = [];
$failedConditions = [];

// Evaluate the target rule
if ($this->targetRule->evaluate($this->facts, $this->allRules)) {
Expand All @@ -69,9 +70,14 @@ public function evaluate(): array
['interpretation' => $this->targetRule->interpretRules()]
);
} else {
$failedConditions = $this->targetRule->getFailedConditions();

$result[] = array_merge(
$this->targetRule->triggerFailureEvent($this->facts),
['interpretation' => $this->targetRule->interpretRules()]
[
'interpretation' => $this->targetRule->interpretRules(),
'failedConditions' => $failedConditions
]
);
}

Expand Down
94 changes: 46 additions & 48 deletions src/Rule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Rule
private array $event;
private array $failureEvent;
private ?string $name;
private array $failedConditions = [];

public function __construct(array $options)
{
Expand All @@ -33,6 +34,8 @@ public function getName(): ?string

public function evaluate(Facts $facts, array $allRules): bool
{
$this->failedConditions = []; // Reset failed conditions before evaluation

if (isset($this->conditions['all'])) {
return $this->evaluateAll($this->conditions['all'], $facts, $allRules);
} elseif (isset($this->conditions['any'])) {
Expand All @@ -52,25 +55,30 @@ private function evaluateAll(array $conditions, Facts $facts, array $allRules):
if (isset($allRules[$dependencyRuleName])) {
$dependencyRule = $allRules[$dependencyRuleName];
if (!$dependencyRule->evaluate($facts, $allRules)) {
$this->failedConditions[] = $condition;
return false;
}
} else {
throw new Exception("Dependent rule '$dependencyRuleName' not found");
}
} elseif (isset($condition['all'])) {
if (!$this->evaluateAll($condition['all'], $facts, $allRules)) {
$this->failedConditions[] = $condition;
return false;
}
} elseif (isset($condition['any'])) {
if (!$this->evaluateAny($condition['any'], $facts, $allRules)) {
$this->failedConditions[] = $condition;
return false;
}
} elseif (isset($condition['not'])) {
if ($this->evaluateCondition($condition['not'], $facts, $allRules)) {
$this->failedConditions[] = $condition;
return false; // Negate the condition
}
} else {
if (!$this->evaluateCondition($condition, $facts, $allRules)) {
$this->failedConditions[] = $condition;
return false;
}
}
Expand All @@ -87,31 +95,46 @@ private function evaluateAny(array $conditions, Facts $facts, array $allRules):
$dependencyRule = $allRules[$dependencyRuleName];
if ($dependencyRule->evaluate($facts, $allRules)) {
return true;
} else {
$this->failedConditions[] = $condition;
}
} else {
throw new Exception("Dependent rule '$dependencyRuleName' not found");
}
} elseif (isset($condition['all'])) {
if ($this->evaluateAll($condition['all'], $facts, $allRules)) {
return true;
} else {
$this->failedConditions[] = $condition;
}
} elseif (isset($condition['any'])) {
if ($this->evaluateAny($condition['any'], $facts, $allRules)) {
return true;
} else {
$this->failedConditions[] = $condition;
}
} elseif (isset($condition['not'])) {
if (!$this->evaluateCondition($condition['not'], $facts, $allRules)) {
return true; // Negate the condition
} else {
$this->failedConditions[] = $condition;
}
} else {
if ($this->evaluateCondition($condition, $facts, $allRules)) {
return true;
} else {
$this->failedConditions[] = $condition;
}
}
}
return false;
}

public function getFailedConditions(): array
{
return $this->failedConditions;
}

private function evaluateCondition(array $condition, Facts $facts, array $allRules): bool
{
$factName = $condition['fact'] ?? null;
Expand All @@ -125,26 +148,17 @@ private function evaluateCondition(array $condition, Facts $facts, array $allRul

$factData = $facts->get($factName, $path);

switch ($operator) {
case 'equal':
return $factData === $value;
case 'lessThanInclusive':
return $factData <= $value;
case 'greaterThanInclusive':
return $factData >= $value;
case 'lessThan':
return $factData < $value;
case 'greaterThan':
return $factData > $value;
case 'in':
return in_array($factData, $value, true);
case 'notIn':
return !in_array($factData, $value, true);
case 'contains':
return is_array($factData) && in_array($value, $factData);
default:
throw new Exception("Unknown operator: $operator");
}
return match ($operator) {
'equal' => $factData === $value,
'lessThanInclusive' => $factData <= $value,
'greaterThanInclusive' => $factData >= $value,
'lessThan' => $factData < $value,
'greaterThan' => $factData > $value,
'in' => in_array($factData, $value, true),
'notIn' => !in_array($factData, $value, true),
'contains' => is_array($factData) && in_array($value, $factData),
default => throw new Exception("Unknown operator: $operator"),
};
}

public function triggerEvent(Facts $facts): array
Expand Down Expand Up @@ -205,34 +219,18 @@ private function interpretCondition(array $condition): string
}

// Mapping operator to a readable format
switch ($operator) {
case 'equal':
$operatorText = 'is equal to';
break;
case 'greaterThanInclusive':
$operatorText = 'is >=';
break;
case 'lessThanInclusive':
$operatorText = 'is <=';
break;
case 'lessThan':
$operatorText = 'is less than';
break;
case 'greaterThan':
$operatorText = 'is greater than';
break;
case 'in':
$operatorText = 'is in';
break;
case 'notIn':
$operatorText = 'is not in';
break;
case 'contains':
$operatorText = 'contains';
break;
default:
throw new Exception("Unknown operator: $operator");
}
$operatorText = match ($operator) {
'equal' => 'is equal to',
'greaterThanInclusive' => 'is >=',
'lessThanInclusive' => 'is <=',
'lessThan' => 'is less than',
'greaterThan' => 'is greater than',
'in' => 'is in',
'notIn' => 'is not in',
'contains' => 'contains',
default => throw new Exception("Unknown operator: $operator"),
};

return "$factDisplay $operatorText $value";
}
}
13 changes: 11 additions & 2 deletions tests/EngineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public function testPlayerIsFouledOut()
$engine->setTargetRule('rule.player.isFouledOut');

$result = $engine->evaluate();

$expectedResult = [
[
'type' => 'fouledOut',
Expand Down Expand Up @@ -98,7 +97,17 @@ public function testProfileIsCompleted()
]
]
],
'interpretation' => '(NOT (username is equal to NULL) AND NOT (birthdayYear is equal to NULL) AND NOT (profilePic is equal to NULL) AND NOT (primaryLocation is equal to NULL))'
'interpretation' => '(NOT (username is equal to NULL) AND NOT (birthdayYear is equal to NULL) AND NOT (profilePic is equal to NULL) AND NOT (primaryLocation is equal to NULL))',
'failedConditions' => [
[
'not' => [
'fact' => 'profile',
'path' => '$.attributes.username',
'value' => NULL,
'operator' => 'equal'
]
]
]
]
];

Expand Down

0 comments on commit 1370cdf

Please sign in to comment.