Hi there - I'm encountering some unexpected behaviour of Drools (6.1.0.Final) when using a simple accumulate function (sum) on a couple of ArrayLists. For example, I have two ArrayLists, both containing random amounts, e.g. [1, 2, 3] and [4, 5, 6]. What I'm trying to get is the sum of the values stored in the ArrayLists from a specific index number. E.g. index 2 should give me 7, index 3; 9. The index number itself is however depended on a different variable ($Timer.getTick() in my example). The condition I'm using is (Data.Amount() are the Arrays):
$Timer : Timer(true)
$Calculate : Number() from accumulate( $Data : Data(true),
sum($Data.getAmount().get($Timer.getTick())) )
$Timer.getTick() starts at 0 and is increased by 1 on a annual basis according to a pseudo-clock in combination with a cron expression used to trigger the rule that performs the update.
Now, what I get as result is for every cycle: 5. That means, that although the $Timer.getTick() is updated every cycle (starting at 0 and adding up to 1, 2, 3, 4, etc), the index reference in the accumulate function uses only 0. First thoughts were that $Timer.getTick() wasn't updated properly, but it does. If I use as condition $Timer : Timer( $Timer.getTick() == 2), the result I get is 9 (only triggered when getTick == 2 of course, but the summation is correct).
What I found out was that :
(i) if I insert another variable in working memory (e.g. $Index.getTick()) and equal that variable to the value of $Timer.getTick()
(ii) put this new variable in the condition part of the rule with the accumulate function including a link with the value of $Timer.getTick(), or in code:
$Timer : Timer(true)
$Index : DetermineIndex( $Chrono.getTick() == $Index.getTick() )
$Calculate : Number() from accumulate( $Data : Data(true),
sum($Data.getAmount().get($Timer.getTick())) )
(for ease of reference, the part in bold is different to the first condition stated above)
The results I then get are 5, 7 and 9. Just as I expected.
Do I somehow miss something? I would expect in the end both rules aren't different as it comes to the condition and accumulate part. Nevertheless, the results are clearly different.
Anyone having an idea on this (below a simple example in code (except for the maybe the cron/pseudo clock part easy to reproduce)?
Thanks
Emiel
declare Timer
Tick : int
Interval : String
end
rule "Insert Timer"
when
eval(true)
then
Timer $Timer = new Timer();
$Timer.setTick(0);
$Timer.setInterval("years")
insert($Timer);
end
//The 'Tick' is updated on an annual basis (running a pseudo-clock and using a cron expression to trigger the update):
rule "Timer - Year cycle"
salience 10
no-loop
timer (cron: 00 00 00 1 1 ? )
when
$Timer : Timer( "years".equals($Timer.getInterval()) )
then
$Timer.setTick($Timer.getTick()+1);
update($Timer);
end
declare Data
Amount : java.util.ArrayList
end
rule "Fill data arrays"
when
eval(true)
then
Data $Data = new Data();
$Data.setAmount(new java.util.ArrayList<Double>());
$Data.getAmount().add(1.0);
$Data.getAmount().add(2.0);
$Data.getAmount().add(3.0);
insert($Data);
end
rule "Fill data array 2"
when
eval(true)
then
Data $Data = new Data();
$Data.setAmount(new java.util.ArrayList<Double>());
$Data.getAmount().add(4.0);
$Data.getAmount().add(5.0);
$Data.getAmount().add(6.0);
insert($Data);
end
rule "Print Data objects in memory"
when
$Data : Data(true)
then
System.out.println("Data objects in memory contain: " +
$Data.getAmount());
end
rule "Sum"
salience -1
when
$Timer : Timer(true)
$Calculate : Number() from accumulate( $Data : Data(true),
sum($Data.getAmount().get($Timer.getTick())) )
then
System.out.println("[Test] Outcome of the accumulate. $Calculate = " +
$Calculate);
end
declare DetermineIndex
Tick : int
end
rule "Insert Index"
when
eval(true)
then
DetermineIndex $Index = new DetermineIndex();
$Index.setTick(0);
insert($Index);
end
rule "Equal Index tick and Timer tick"
when
$Timer : Timer(true)
$Index : DetermineIndex( $Index.getTick() < $Timer.getTick() )
then
$Index.setTick($Timer.getTick());
update($Index);
end
rule "Sum with 'determine'index"
salience -2
when
$Timer : Timer(true)
$Index : DetermineIndex( $Chrono.getTick() == $Index.getTick() )
$Calculate : Number() from accumulate( $Data : Data(true),
sum($Data.getAmount().get($Timer.getTick())) )
then
System.out.println("[Test] Outcome of the accumulate (with extra condition on index). $Calculate = " +
$Calculate);
System.out.println("[Test] Tick from Timer class is: " +
$Chrono.getTick());
System.out.println("[Test] Tick from Index class is: " +
$Chrono.getTick());
end