问题描述
这是一个排班计划应用程序。我已经通过改变重量来动态控制一些约束的开/关,这很棒。某些特定的约束已经可以通过计划对象属性(员工合同的最大值)动态控制。我仍然没有找到一种方法来根据配置对ConstraintProvider进行参数化。我的问题是:
可以通过编程方式创建ConstraintProvider而不是在SolverConfig.xml中进行定义吗?这样我就可以注入自己的参数
我希望可以不仅仅以10小时的固定持续时间(即10 * 60的硬编码值)来动态调整此约束条件:
Constraint breakBetweenNonConsecutiveShiftsIsAtLeastTenHours(ConstraintFactory constraintFactory) {
return getAssignedShiftConstraintStream(constraintFactory)
.join(Shift.class,equal(Shift::getEmployee),lessthan(Shift::getEndDateTime,Shift::getStartDateTime))
.filter((s1,s2) -> !Objects.equals(s1,s2))
.filter((s1,s2) -> s1.getEndDateTime().until(s2.getStartDateTime(),ChronoUnit.HOURS) < 10)
.penalizeConfigurableLong(CONSTRAINT_BREAK_BETWEEN_NON_CONSECUTIVE_SHIFTS,(s1,s2) -> {
long breakLength = s1.getEndDateTime().until(s2.getStartDateTime(),ChronoUnit.MINUTES);
return (10 * 60) - breakLength;
});
}
(我可以在Shift上添加一个字段,以为所有班次返回相同的值,但这很麻烦。)
解决方法
当前,最好的方法是创建一个自定义类来存储持续时间(例如:MinimumBreakBetweenNonConsecutiveShifts),将其添加为花名册的字段,并用@ProblemFact
注释该字段。然后,您可以使用constraintFactory.from(...).join(MinimumBreakBetweenNonConsecutiveShifts.class)
将带有问题事实的信息流加入流中。我们目前在这里讨论访问问题事实的替代方法:https://kie.zulipchat.com/#narrow/stream/232679-optaplanner/topic/Constraint.20context
(https://github.com/kiegroup/optaweb-employee-rostering/issues/502#issuecomment-701479372)