首页 > 解决方案 > Optaplanner 为 ConstraintProvider 类中的员工允许的最大轮班数量添加约束

问题描述

我正在尝试添加一个约束,以限制在 ConstraintProvider 类中分配给员工的班次数量,但我想知道是否有更好的方法来定义它,而不是必须在我的 @PlanningEntity 和 @PlanningVariable 类中添加一个属性?

这是我的@PlanningEntity 类属性:

 @PlanningEntity
    @Entity
    public class Shift {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "shiftId")
        private int shiftId;

        @Column(name = "startTime")
        private LocalTime startTime;

        @Column(name = "endTime")
        private LocalTime endTime;

        @Column(name = "day")
        private String day;

        @Column(name = "requiredSkillLevel")
        private int requiredSkillLevel;

        @Column(name = "shiftAmount")
        private int shiftAmount;

        @Transient
        @PlanningVariable(valueRangeProviderRefs = "employee")
        private Employee employee;

这是我的@PlanningVariable 类:

    @Entity
    public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "employeeId")
    private int employeeId;

    @Column(name = "employeeName")
    private String employeeName;

    @Column(name = "skillLevel")
    private int skillLevel;

    @Column(name = "employeeType")
    @Enumerated(EnumType.STRING)
    private EmployeeType employeeType;

    @Column(name = "associatedDepartment")
    @Enumerated(EnumType.STRING)
    private Departments associatedDepartment;

    @Column(name = "weeklyShiftAllowance")
    private int weeklyShiftAllowance;

我的约束如下:

    public class ScheduleConstraintProvider implements org.optaplanner.core.api.score.stream.ConstraintProvider {
    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[]{
                requiredSkillLevelOfEmployeesForShifts(constraintFactory),
                maximumNumberOfAllowableShiftsForEmployees(constraintFactory)
        };
    }

    private Constraint maximumNumberOfAllowableShiftsForEmployees(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Shift.class)
                .groupBy(Shift::getEmployee, sum(Shift::getShiftAmount))
                .filter((employee, shiftAmount) -> shiftAmount > employee.getWeeklyShiftAllowance())
                .penalize("Weekly Shift Allowance for each Employee",
                        HardSoftScore.ONE_HARD,
                        (employee, shiftAmount) -> shiftAmount - employee.getWeeklyShiftAllowance());
    }

    private Constraint requiredSkillLevelOfEmployeesForShifts(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Shift.class)
                .groupBy(Shift::getEmployee, sum(Shift::getRequiredSkillLevel))
                .filter((employee, requiredSkillLevel) -> requiredSkillLevel > employee.getSkillLevel())
                .penalize("Required Skill Level for a Shift",
                HardSoftScore.ONE_HARD,
                (employee, requiredSkillLevel) -> requiredSkillLevel - employee.getSkillLevel());
    }


}

除了在我的 Shift 类中添加 shiftAmount 之外,我还可以添加一些将每个 Shift 视为 1 个班次分配的内容吗?

标签: javaspring-bootstreamconstraintsoptaplanner

解决方案


是的

代替:

return constraintFactory.from(Shift.class)
                .groupBy(Shift::getEmployee, sum(Shift::getShiftAmount))

return constraintFactory.from(Shift.class)
                .groupBy(Shift::getEmployee, count())

(如果你想要一个长的,使用countLong()。)


推荐阅读