Skip to content
This repository has been archived by the owner on Sep 20, 2021. It is now read-only.

Produce results in response of rule evaluations #94

Open
5 tasks
jubianchi opened this issue Sep 14, 2016 · 5 comments
Open
5 tasks

Produce results in response of rule evaluations #94

jubianchi opened this issue Sep 14, 2016 · 5 comments

Comments

@jubianchi
Copy link
Member

jubianchi commented Sep 14, 2016

Ruler is well designed for writing rules and making assertions on them (i.e checking if some input validates the rule).

An nice feature would to be able to produce any result in response of these assertions (i.e if some input validates a rule then the engine should provide us a value).

Let's take a simple example:

  • If I'm at least 16 years old, I can buy beer
  • If I'm at least 18 years old, I can buy whiskey, gin or vodka

With only ruler, I would have to write two rules:

  • $r1 = 'person.age >= 16'
  • $r2 = 'person.age >= 18'

And some PHP code:

<?php

$ruler = new Hoa\Ruler\Ruler();
$context = new Hoa\Ruler\Context();
$context['person'] = new Person();
$context['person']->age = 19;

$beverages = [];

if ($ruler->assert($r1, $context)) {
    $beverages[] = 'beer';
}

if ($ruler->assert($r2, $context)) {
    $beverages[] = 'whiskey';
    $beverages[] = 'gin';
    $beverages[] = 'vodka';
}

var_dump($beverages); 

/*
array(4) {
  [0] => string(3) "beer",
  [1] => string(3) "whiskey",
  [2] => string(3) "gin",
  [3] => string(3) "vodka"
}
*/

This is not really efficient: the more rules I have, the more code I need to write. If the results change, I'll have to change my PHP code, ...

What I propose here is something more flexible:

$ruler = new Hoa\Ruler\Ruler();
$rules = new Hoa\Ruler\Rules();
$context = new Hoa\Ruler\Context();
$context['person'] = new Person();
$context['person']->age = 19;

$rules->add('16yo', new Hoa\Ruler\Rules\ThenElse('person.age >= 16', ['beer'], ['water']), 1);
$rules->add('18yo', new Hoa\Ruler\Rules\Then('person.age >= 18', ['whiskey', 'gin', 'vodka']), 2);

var_dump($rules->getBestResult($ruler, $context));
/*
array(3) {
  [0] => string(3) "whiskey",
  [1] => string(3) "gin",
  [2] => string(3) "vodka"
}
*/

var_dump($rules->getAllResults($ruler, $context));
/*
array(2) {
  '18yo' => array(3) {
    [0] => string(3) "whiskey",
    [1] => string(3) "gin",
    [2] => string(3) "vodka"
  },
  '16yo' => array(1) {
    [0] => string(3) "beer"
  }
}
*/

Let me explain:

  • Hoa\Ruler\Rules is a collection of rules, ordered by a priority,
  • it has a add(string $id, Rule $rule, int $priority) method,
  • the $id lets us reuse the rule result in following rules,
  • the $rule is a standard ruler rule (a string or a compiled rule) wrapped in a Then or ThenElse class,
  • the $priority is used to order the collection (higher priority will run first);
  • we can ask for the best results (getBestResult) which will be the result of the higher priority rule validating the context,
  • we can ask for all results (getAllResults) of valid rules

This kind of feature will allow for more generic code when it comes to work with rules and produce results depending on them.

The Rules collection can easily be built with results coming from a database.

What has to be done:

  • Implement the Rules collection (first with an SplPriorityQueue and then with the hoa/heap library)
  • Implement the Then rule class (it returns a result when the rule validates the input)
  • Implement the ThenElse rule class (it returns a result when the rule validates the input and another when the rule does not validate the input)
  • Implement an algorithm to resolve rules dependencies (indeed, a rule can depend on another one). hoa/graph could be a good candidate for this kind of work.
  • Implement a rule() function to reference the result of one rule from another rule

Let me know if I forgot something. I have a working POC which needs some cleanup.

@Hywan Hywan changed the title Produce results in response of rules evaluation Produce results in response of rule evaluations Sep 14, 2016
@Hywan Hywan self-assigned this Sep 14, 2016
@Hywan
Copy link
Member

Hywan commented Sep 14, 2016

That's an excellent idea.
I would change the API though. Why not having:

Rules::add(string $id, $ruleKind, int $priority)

where $ruleKind is a Then or other rule.
Thus, behind add, we will have a graph.

Thoughts?

@jubianchi
Copy link
Member Author

@Hywan you are totally right. I made some mistake while writing the issue. They are now fixed.

@Hywan
Copy link
Member

Hywan commented Sep 14, 2016

@jubianchi What do you think of my API proposal?

@Grummfy
Copy link
Member

Grummfy commented Sep 14, 2016

yeah! far better!

@jubianchi
Copy link
Member Author

jubianchi commented Sep 14, 2016

@Hywan I'm totally ok with your API proposal, I edited the issue's description:

  • [the Hoa\Ruler\Rules class] has a add(string $id, Rule $rule, int $priority) method,
    [...]
  • the $rule is a standard ruler rule (a string or a compiled rule) wrapped in a Then or ThenElse class,

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

3 participants