我正在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