Search code examples
droolsoptaplanner

In drools DRL check that an array of objects doesnt have a value


I'm trying to add a new rule to the employee rostering example in optaplanner business central. A rule to check that if a shift is assigned to an employee outside of his schedule then lowers the hard constraint score holder.

package employeerostering.employeerostering;

rule "ShiftHoursWithinEmployeeSchedule"
    dialect "mvel"
    when
        $shiftAssignment : ShiftAssignment( $employee : employee != null, $shiftEndDateTime : shift.timeslot.endTime, $shiftStartDate : shift.timeslot.startTime)

        not Schedule ( day == $shiftEndDateTime.dayOfWeek.getValue() && (startTime > $shiftStartDateTime || endTime < $shiftEndDateTime) ) from $employee.schedules

    then
        scoreHolder.addHardConstraintMatch(kcontext, -1);
end

I'm new into DRL, i want to modify the second rule so it loops over all schedules of the $employee and checks if there isnt a single one that fulfills the condition.


Solution

  • I think you just need to flip the relational operators because you want to penalize a situation when there is no schedule such that the shift fits into the schedule:

    not Schedule ( day == $shiftEndDateTime.dayOfWeek.getValue() && (
            startTime < $shiftStartDateTime &&
            endTime > $shiftEndDateTime)
    ) from $employee.schedules
    

    Not sure what is the type of Schedule.startTime. If it's a day time offset (e.g. 8:00) then you probably can't compare it to Timeslot.startTime which is probably an absolute time amount (date + time).

    I would recommend to reuse Timeslot type in Schedule instead of defining the schedule as day + time. Then you should be able to write:

    rule "ShiftHoursWithinEmployeeSchedule"
        dialect "mvel"
        when
            $shiftAssignment : ShiftAssignment( $employee : employee != null, $shiftEndDateTime : shift.timeslot.endTime, $shiftStartDate : shift.timeslot.startTime)
    
            not Schedule ( timeslot.startTime > $shiftStartDateTime && timeslot.endTime < $shiftEndDateTime ) from $employee.schedules
    
        then
            scoreHolder.addHardConstraintMatch(kcontext, -1);
    end