如何总结一周的轮班时间

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

我在事实收集 DaySetting 方面遇到问题。

public class DaySetting {
    String businessDate;
    Integer weekNo;
    Integer monthNo;
}

我还有一个班次:

public class Shift {
    @PlanningId
    private String id;

    private LocalDateTime start;
    private LocalDateTime end;

     public Long getShiftDuration() {
        long minutes = ChronoUnit.MINUTES.between(start, end);
        
        return minutes;
    }
    public String getStartDate() {
     DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
     String dateStr = getStart().toLocalDate().format(formatter);
     return dateStr;
   }
}

日期设置可以采用如下值:

public class DaySetting {
    String businessDate = 2024-06-01;
    Integer weekNo = 1; // first week of June
    Integer monthNo = 6;//June
}
public class DaySetting {
    String businessDate = 2024-06-02;
    Integer weekNo = 1; // first week of June
    Integer monthNo = 6;//June
}
public class DaySetting {
    String businessDate = 2024-06-09;
    Integer weekNo = 2; // Second week of June
    Integer monthNo = 6;//June
}

public class DaySetting {
    String businessDate = 2024-06-10;
    Integer weekNo = 2; // second week of June
    Integer monthNo = 6;//June
}

我必须根据周来总结工作的持续时间没有值。对于第 1 周,有 2 个班次,将进行总结。前两个班次持续时间将汇总为第 1 周,

后两个班次将在第 2 周进行总结。

所以,到目前为止我在下面尝试过:

Constraint workingHoursLessThanMaximumInContractPerWeek(ConstraintFactory constraintFactory) {
        return  constraintFactory.forEach(DaySetting.class)
                .join(Shift.class)
                .groupBy((daySetting, shift) -> day.getWeekNo(),
                         ConstraintCollectors.sumLong((daySetting, shift) -> shift.getShiftDuration()))
//Shift don't have weekNo field. It only have getStartDate() to get the business date, 
//so we have to take the date value from DaySettings class and match with the date of Shift class. How to achieve this with the constraints.
                .penalize(HardMediumSoftScore.ONE_SOFT, ((weekNo, sumValue))->{
                    return sumValue;
                })
                .asConstraint("Working Hours Greater Than Maximum In Contract Per Week");
    }
java optaplanner timefold
1个回答
0
投票

我建议将

DaySetting
放入
Shift
以避免因跨多天的轮班(例如夜班)而产生歧义。此外,还应包括年份,否则在跨年度规划时间表时可能会出现问题。我将创建一个
WeekIdentifier
记录,将
LocalDate
映射到一年中的一年 + 一周:

public record WeekIdentifier(long year, long weekInYear) {
    private final static WeekFields WEEK_DEFINITION =   WeekFields.of(DayOfWeek.MONDAY, 7);
    
    public static WeekIdentifier forDate(LocalDate date) {
        return new WeekIdentifier(WEEK_DEFINITION.weekBasedYear().getFrom(date),
                                  WEEK_DEFINITION.weekOfWeekBasedYear().getFrom(date));
    }
} 

然后我会添加一个方法来获取

WeekIdentifer
Shift
:

// Assumption, Shift is a @PlanningEntity with a @PlanningVariable employee
@PlanningEntity
public class Shift {
    @PlanningId
    private String id;

    private LocalDateTime start;
    private LocalDateTime end;
    
    @PlanningVariable
    private Employee employee;

     public Long getShiftDuration() {
        long minutes = ChronoUnit.MINUTES.between(start, end);
        
        return minutes;
    }
    
    public WeekIdentifier getWeekIdentifier() {
        return WeekIdentifier.forDate(getStart().toLocalDate());
    }
    
    public Employee getEmployee() {
        return employee;
    }
}

然后我会这样写

Constriant

Constraint workingHoursLessThanMaximumInContractPerWeek(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(Shift.class)
               .groupBy(Shift::getEmployee,
                        Shift::getWeekIdentifier,
                        ConstraintCollectors.sumLong(Shift::getShiftDuration))
               .filter((employee, week, minutes) -> minutes > employee.getMaximumMinutesPerWeek())
               .penalize(HardMediumSoftScore.ONE_SOFT, (employee, week, minutes) -> {
                   return minutes - employee.getMaximumMinutesPerWeek();
               })
               .asConstraint("Working Hours Greater Than Maximum In Contract Per Week");
}
© www.soinside.com 2019 - 2024. All rights reserved.