I am trying to write a rule that collects / accumulates values based on a temporal operator.
rule "Zone6 Overlap"
when
$i1 : Instance ($e1 : event == " Vel : 20.99-23.98 km/h : " && $name1 : name) from entry-point "Stream"
$i2 : Instance ($e2 : event && $name2 : name && $e2 == $e1 && $name2 != $name1
&& this overlaps $i1) from entry-point "Stream"
then
System.out.println("** Overlap Event: Velocity Zone 6 ** \nPlayer1: " + $i1.getName() + "\nPlayer2: "
+ $i2.getName() + "\nEvent: " + $i1.getEvent() + "\n" + "Start Time (P1): "
+ $i1.getStart() + " - End Time: " + $i1.getEnd() + "\nStart Time (P2): "
+ $i2.getStart() + " - End Time: " + $i2.getEnd() + "\n");
end
This is my original rule which manages to get the overlap of two durations.
The idea of the rule i want to create is to see if there are any collective overlaps of the durations of players in a football game. I want to see if any of up to the 9 players on the field are travelling at a range of speed specified as a string in the event variable that are all overlapping at once.
I've tried a few things regarding accumulate and collect but struggling with how to collect these events when they happen and return them to the right hand side of the rule so they can be printed to standard out.
Please help.
Thanks.
It should be possible to create a rule to match your requirements, but I think you need to be aware of the exact definition of the overlaps keyword in Drools:
The overlaps evaluator correlates two events and matches when the current event starts before the correlated event starts and finishes after the correlated event starts, but before the correlated event finishes. In other words, both events have an overlapping period.
That means that it will not match any arbitrary overlap, but only if one event both starts before another event's start and ends before that event's end. Let's assume we have the following 3 events:
A [11:19:00-11:19:30]
B [11:19:15-11:19:45]
C [11:19:20-11:19:40]
In this case, A starts before B and C, and also ends before both. That means A overlaps B and C. However, B does not overlap C, because it starts before C, but it ends after C. For a full definition of each of the available operators, see the Drools fusion documentation.
If that matches your use case, the following rule will collect all events that overlap a given event:
rule "Overlap"
when
$i1 : Instance ($e1 : event == "some event" )
$instances : List( size > 0 ) from collect ( Instance ( event == $e1, this != $i1,
this overlappedby $i1 ) )
then
System.out.println("** Overlap Event for: " + $i1.getName());
for (int i = 0; i < $instances.size(); i++) {
System.out.println("Overlaps: " + ((Instance)$instances.get(i)).getName());
}
end
As you can see, it uses the overlappedby keyword, which is the inverse of overlaps.