简体   繁体   中英

OptaPlanner Custom Employee Rostering - Issues with WeeklyHoursLimit in the Constraint Provider

I have been following the employee rostering example to create a custom employee scheduling service. I am trying to implement the weekly hours limit. However, I have not been able to achieve the desired constraint of a maximum of 40 hours worked per week per Employee. I've tried to replicate the OptaPlanner Employee Rostering Solution. This is what I've come up with, but the solution returns no matches no matter what input I try.

 Constraint weeklyHoursUpperLimit(ConstraintFactory constraintFactory) {
    return constraintFactory.from(Employee.class)
            .join(Schedule.class, equal(Function.identity(), Schedule::getEmployee))
            .groupBy((employee, schedule) -> employee,
                    ((employee, schedule) -> ZonedDateTime.parse(schedule.getTimeslot().getStart()).toLocalDate()
                            .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))),
                    sumDuration((employee, schedule) -> Duration.between(ZonedDateTime.parse(schedule.getTimeslot().getStart()),
                            ZonedDateTime.parse(schedule.getTimeslot().getEnd()))))
            .filter((practitioner, day, time) -> time.toHoursPart() > 40)
            .penalize("Practitioners cannot work more than 40 hours per week", HardMediumSoftScore.ONE_HARD);

The solution, a list of type Schedule containing an Employee and the corresponding timeslot, does not seem to ever match the desired behavior.

Using the following input:

{
    "employees": [
        {
            "id": "0458d419-da18-4d86-82de-31a2272f018a"
        }
    ],
    "timeslots": [
        {
            "start": "2021-05-24T00:00:00-04:00",
            "end": "2021-05-24T12:00:00-04:00",
            "slotId": 1
        },
        {
            "start": "2021-05-24T12:00:00-04:00",
            "end": "2021-05-25T00:00:00-04:00",
            "slotId": 7
        },
        {
            "start": "2021-05-25T12:00:00-04:00",
            "end": "2021-05-26T00:00:00-04:00",
            "slotId": 4
        },
        {
            "start": "2021-05-27T12:00:00-04:00",
            "end": "2021-05-28T00:00:00-04:00",
            "slotId": 5
        }
    ]
}

The ScoreExplanation says this: constraint (Practitioners cannot work more than 40 hours per week) has 0 matches.

What it should say: constraint (Practitioners cannot work more than 40 hours per week) has 1 matches.

With this input, the only possible solution must match this constraint. Other constraints are detected and penalized, so I am wondering why this one never returns any matches.

I suspect the problem is in the filter: .filter((practitioner, day, time) -> time.toHoursPart() > 40)

Duration#toHoursPart() returns a remainder after dividing total hours by hours in a day, which is between 0 and 23. The filter should probably use Duration#toHours() instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM