实施方式员工可以在流氓的OptaPlanner护士名单示例中工作的最大天数

时间:2016-04-25 17:57:47

标签: drools optaplanner

我正在OptaPlanner的一个项目,该项目接近护士名册示例,我正试图找到一种方法来实施约束"员工在调度期间可以工作的最长天数"。仅举一例,员工每天可以轮班工作。 目前我实施的是:

使员工类成为一个计划实体并放置一个@InverseRelationShadowVariable,它将保存员工分配到的shiftAssignment实例

@PlanningEntity
public class ShiftAssignment extends AbstractPersistable {

protected List<ShiftAssignment> employeeAssignedToShiftAssignments;

@InverseRelationShadowVariable(sourceVariableName = "employee")
public List<ShiftAssignment> getEmployeeAssignedToShiftAssignments() {
    return employeeAssignedToShiftAssignments;
}

}

然后创建了一个方法,每次shiftAssignment实例获得新员工时,都会从drools调用该方法。这里循环遍历@InverseRelationShadowVariable列表并将不同的日期放入列表中,并检查列表中是否存在shiftAssignment dayIndex,然后将其添加,否则不添加,最后返回大小列表,即员工工作的不同日期的数量

public static int employeeMaxDaysPerPeriod(Employee employee) {
    List<ShiftAssignment> shiftAssignments = employee.getEmployeeAssignedToShiftAssignments();
    if(shiftAssignments == null)
    {
        return 0;
    }
    List<Integer> shiftAssignmentsDifferentDays = new ArrayList<>();
    for (ShiftAssignment shiftAssignment : shiftAssignments) {
        int shiftDayIndex = shiftAssignment.getShiftDateDayIndex();
        if (!shiftAssignmentsDifferentDays.contains(shiftDayIndex)) {
            shiftAssignmentsDifferentDays.add(shiftDayIndex);
        }
    }
    return shiftAssignmentsCountInDays.size();
}

最后在drools中创建了一个规则,每次员工被分配到shiftAssignment时都会被触发。它的作用是检查&#34; differentDaysInPeriod&#34;分配给员工的人数大于员工可以处理的最长工作天数,并添加违反超出天数的约束

rule "maxDaysInPeriod"
when
$shiftAssignment : ShiftAssignment(employee != null)
then
int differentDaysInPeriod = Settings.employeeMaxDaysPerPeriod($shiftAssignment.getEmployee());
int maxDaysInPeriod = $shiftAssignment.getEmployee().getMaxDaysInPeriod();
if(differentDaysInPeriod > maxDaysInPeriod)
{
scoreHolder.addHardConstraintMatch(kcontext, differentDaysInPeriod - maxDaysInPeriod);
}
end

我想知道这个实现是否良好,如果没有,那么如何实现它就像MinMaxConsecutiveDays约束:

rule "insertEmployeeConsecutiveAssignmentStart"
    salience 2 // Do these rules first (optional, for performance)
when
    ShiftAssignment(
        $employee : employee, employee != null,
        $dayIndex : shiftDateDayIndex,
        $shiftDate : shiftDate
    )
    // The first day has no working day before it
    not ShiftAssignment(employee == $employee, shiftDateDayIndex == ($dayIndex - 1))
then
    insertLogical(new EmployeeConsecutiveAssignmentStart($employee, $shiftDate));
end
rule "insertEmployeeConsecutiveAssignmentEnd"
    salience 2 // Do these rules first (optional, for performance)
when
    ShiftAssignment(
        $employee : employee, employee != null,
        $dayIndex : shiftDateDayIndex,
        $shiftDate : shiftDate
    )
    // The last day has no working day after it
    not ShiftAssignment(employee == $employee, shiftDateDayIndex == ($dayIndex + 1))
then
    insertLogical(new EmployeeConsecutiveAssignmentEnd($employee, $shiftDate));
end

rule "insertEmployeeWorkSequence"
    salience 1 // Do these rules first (optional, for performance)
when
    EmployeeConsecutiveAssignmentStart(
        $employee : employee,
        $firstDayIndex : shiftDateDayIndex
    )

    EmployeeConsecutiveAssignmentEnd(
        employee == $employee,
        shiftDateDayIndex >= $firstDayIndex,
        $lastDayIndex : shiftDateDayIndex
    )

    // There are no free days between the first and last day
    not EmployeeConsecutiveAssignmentEnd(
        employee == $employee,
        shiftDateDayIndex >= $firstDayIndex && < $lastDayIndex
    )
then
    insertLogical(new EmployeeWorkSequence($employee, $firstDayIndex, $lastDayIndex));
end

0 个答案:

没有答案