OptaPlanner有没有办法写连续groupBy的约束?

问题描述 投票:0回答:0

我正在尝试写一个关于“连续两周工作总时数不能超过80小时”的约束条件

当前约束如下,有效,

Constraint atMost80HoursFor2Weeks(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(ShiftAssignment.class)
            .filter(shift -> !shift.getDuration().isZero())
            .groupBy(ShiftAssignment::getEmployee, toList())
            .penalizeConfigurable((employee, shiftList) -> {
                Map<Integer, Duration> shiftMap = shiftList.stream().collect(Collectors.toMap(ShiftAssignment::getWeekIndex, ShiftAssignment::getDuration, Duration::plus));
                int overHour = 0;

                for (Integer week : shiftMap.keySet()) {
                    if (shiftMap.containsKey(week + 1)) {
                        overHour += Math.max(0, shiftMap.get(week).plus(shiftMap.get(week + 1)).toMinutes() / 60 - 80);
                    }
                }

                return overHour;
            })
}

但是,我想知道我是否可以使用 join 和 groupBy。我想到了类似下面的代码,但我无法加入两个 TriConstraintStream。有没有更聪明的方法来写这个约束?

return constraintFactory.forEach(ShiftAssignment.class)
        .filter(shift -> !shift.getDuration().isZero())
        .groupBy(ShiftAssignment::getEmployee, ShiftAssignment::getWeekIndex, toList())
        .join(constraintFactory.forEach(ShiftAssignment.class)
                .groupBy(ShiftAssignment::getEmployee, ShiftAssignment::getWeekIndex, toList()),
                Joiners.equal((emp, week, shiftList) -> emp, (emp, week, shiftList) -> emp),
                Joiners.equal((emp, week, shiftList) -> week + 1, (emp, week, shiftList) -> week)
        )
optaplanner
© www.soinside.com 2019 - 2024. All rights reserved.