[rules-users] function in drools

Davide Sottara dsotty at gmail.com
Fri Sep 28 17:50:04 EDT 2012


Ok, so you may need something like this:


1) You need a bean to store the parameter. You can declare it in DRL, or 
use a normal java class and insert the instance from the main.
The DRL version would be this:

declare Parameters
   threshold : double
end

rule "Initialize"
salience 9999 // fire first!
when
then
   insert( new Parameters( 10.0 ) );    // your value here
end

Or, you can set a global:
// in java:
kSession.setGlobal( "threshold", 1.0 );
// in DRL, at the beginning:
global Double threshold;



2) You need rule "one" and something to hold your current average 
temperature:
( ps. sorry, the $pers : person : Person() was a typo! :) )
Now: do you need to relate the temperature to the person? I mean, how 
many Person
are there in your workingmemory? I guess one, also considering that the 
SensorReading
are not related to the person... In any case, here Person is acting as 
an "enabler fact"
or "guard" which effectively decides if the rule is applicable or not. So:

declare AverageTemperatureRecord  // again, this or a java class
   value : double
end

rule "one"
$pers : Person( gender == 'M' )
   accumulate (
       SensorReading( $temp : temperature ) over window:time( 10m ),
                $avg : average( $temp );
then
  insertLogical( new AverageTempRecord( $avg ) );
end


Notice the use of "insertLogical" : your average will change over time
(but see my remark about rule 2 below), so you may want to keep
only the latest value, or a "history" with all of them?
InsertLogical will make sure that a fact is retracted when its conditions
no longer hold, and in case of an accumulate this is done when the
aggregation set changes, i.e. whenever a SensorReading slides in or
out of the window... The net effect is that the latest will take
the place of the previous, which is different from keeping them all
in memory, or keeping one an modifying it every time - all behaviours
that can be obtained with slightly different rules.

3) Now you can write rule two: If you have the parameter object:

rule "two"
   Parameters( $max : threshold )
   $a : AverageTemperatureRecord( $avg  : avg>  $max )
then
   // do something
end

or you can use the global :


rule "two with global "
   $a : AverageTemperatureRecord( $avg  : avg>  threshol )
then
   // do something
end


notice that your previous rule


rule "two - previous"
   $p : Person( gender == 'M' )
   Parameters( $max : threshold )
   $a : AverageTemperatureRecord( $avg  : avg>  $max )
then
   // do something
   retract( $p );
end


This rule - which does not need an agenda group - will be EVALUATED for 
every new AvgTempRecord (insertLogical will make
sure that only the last remains in the WM, but this will not affect the 
evaluations: every ATR will be checked).
[ Notice that this is not a "call", but a producer-consumer relation 
mediated by the working memory. Rule one generates some
data and drops them into a common environment. Rule two "picks it up" 
and sees whether it matches its conditions or not.
You WOULD probably need the agenda-groups if other sources could 
generate the ATRs for rule "two", but here rule "two"
can only be activated after rule "one" has fired, producing the 
necessary fact]

If at some point the > constraint is satisfied, the rule will be 
ACTIVATED and then FIRED. If the consequence retracts $p,
as you were doing, the guard patterns will no longer satisfied and rule 
"one" (and two) will not be activated anymore.



On 09/28/2012 11:01 AM, thano wrote:
> First of all many thanks for helping me here. I completely agree with you
> that I need to look into the basics. I will definitely start with drools
> manual and examples.
>
> coming back to the example which may not make a complete sense; I have a
> deadline to meet and therefore, I dont have much time to look around. I
> really appreciate your efforts for explaining my example. Basically, This is
> what I am trying to achieve
>
> rule 1 should check a condition and then perform the average. It also
> retrieve a threshold from a class (just to show that). It then jump to rule
> 2 and thats why I used  the agenda group.
>
> rule 2 should only compare the average and the threshold. It should have
> access to the average and the threshold. That is why i thought of inserting
> them as facts in the first rule.
>
> could you please look into the code below and give me further advise.
>
> much appreciated
>
> declare parameters
> avg:double
> end
>
> rule "one"
> $pers : person : Person( gender == 'M' ) // why $pers : person and not only
> $pers
>   accumulate (
>        SensorReading( $temp : temperature ) over window:time( 10m ),
>                 $avg : average( $temp );
> then
>   insertLogical( /*$pers,*/ new AverageTempRecord( $avg ) ); // could you
> please explain this. How exactly it should appear
> drools.setFocus ("Two");
> end
>
>
> rule "two"
> //should only compare avg>threshold
> agenda-group "Two"
>    $p : Person()  // I want threshold here
>    $a : AverageTemperatureRecord( /* pers == $p, */   $avg  : avg )
> then
> end
>
>
>
>
>
> --
> View this message in context: http://drools.46999.n3.nabble.com/function-in-drools-tp4020021p4020047.html
> Sent from the Drools: User forum mailing list archive at Nabble.com.
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>



More information about the rules-users mailing list