deliveredtechnologies / rulebook

100% Java, Lambda Enabled, Lightweight Rules Engine with a Simple and Intuitive DSL
http://www.deliveredtechnologies.com
Apache License 2.0
716 stars 124 forks source link

Fact checking before evaluating rules #204

Open AlDante opened 3 years ago

AlDante commented 3 years ago

Hi,

I am currently trying to use RuleBook to define a bidding system for bridge. It seems well suited for this - typically a bidding system has rules such as "If you have a no trump shape and 12-14 high card points, open One No Trump".

While testing my rule book I noticed that I had, in the test, forgotten to define some facts that the RuleBook needed to evaluate the hand. For example, maybe I forgot to set the value of the high card points - then the RuleBook has insufficient information to return a result.

Is there a standard way of checking that all required facts have been defined before a RuleBook call?

Code example below (where I have forgotten to define a fact "openingSuit" which the RuleBook wants).

class TestAcolBidRuleBook {

    private static RuleBook<Bid> acolBidRuleBook;
    private static final FactMap<Integer> acolBidFacts = new FactMap<>();

    @Test
    void testRules() {

        acolBidRuleBook = RuleBookBuilder.create(AcolBidRuleBook.class).withResultType(Bid.class)
            .withDefaultResult(Bid.NO_BID)
            .build();

        acolBidFacts.setValue("hcp", 12);
        acolBidFacts.setValue("maxSuitLen", 6);
        acolBidFacts.setValue("handType", HandType.NOTRUMP.getAsInt());

        acolBidRuleBook.run(acolBidFacts);

        Optional<Result<Bid>> bidResult = acolBidRuleBook.getResult();
        boolean bidPresent = bidResult.isPresent();

        acolBidRuleBook.getResult().ifPresent(result -> System.out.println("Hand would bid: " + result));
    }
}
Clayton7510 commented 3 years ago

That's an interesting question. While there is no specific mechanism for checking that required facts exist, there are a few tools at your disposal with RuleBook. I also think that it might be a nice feature addition to add targeted functionality to specify required facts.

In the meantime, you could certainly have a precondition rule that does nothing but check facts and either return no result or throw an exception (based on your logic) if certain facts are not available. Another option could be to create a facade on top of your RuleBook that requires certain facts to be added prior to executing the RuleBook.

AlDante commented 3 years ago

I like the precondition rule idea, thanks. How do I continue rule processing if the preconditions are satisfied? I thought rule processing stopped when the first matching rule fires.