You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过.map()与Join将约束流基数提升至5?技术实现咨询

解决方案

针对你的问题,我们可以通过封装上下文数据、完善关联逻辑来解决,具体修改如下:

1. 定义上下文封装类(Java 16+ 用Record,低版本用带Getter的POJO)

先把需要传递的多维度数据封装成一个对象,方便下游统一提取:

// 放在当前类内部或单独创建类,低版本替换为普通POJO
private record RuleE015Context(RuleSetting ruleSetting, Employee employee, Integer weekNo, Long totalDuration) {}

2. 填充.map()函数

将groupBy过滤后的四个参数打包到上下文对象中,向下游传递:

.map((ruleSetting, employee, weekNo, totalDuration) -> new RuleE015Context(ruleSetting, employee, weekNo, totalDuration))

3. 修正join(ForeignerType.class)的关联逻辑

必须添加匹配条件,确保基于员工的外籍类型关联正确的ForeignerType,避免无效的笛卡尔积:

.join(ForeignerType.class, 
    (context) -> context.employee().getForeignerType(),
    (foreignerType) -> foreignerType.getForeignerType())

4. 在penalizeConfigurable中提取数据并应用基数提升规则

此时第一个参数是我们封装的上下文对象,直接从中提取所需数据,同时将基数提升至5:

.penalizeConfigurable((context, foreignerType) -> {
    RuleSetting ruleSetting = context.ruleSetting();
    Employee employee = context.employee();
    Long totalDuration = context.totalDuration();
    
    // 计算惩罚值,乘以5实现基数提升
    double ratio = (double) totalDuration / employee.getContracts().getMaxMinutesPerWeek();
    double penalty = Math.abs(ratio) * Math.abs(ruleSetting.getWeight()) * 5;
    return penalty.intValue();
})

5. 调整indictWith的参数

同样从上下文对象中提取数据生成EmployeeScoreKeyItems:

.indictWith((context, foreignerType) -> {
    RuleE015Context ctx = (RuleE015Context) context;
    EmployeeScoreKeyItems res = new EmployeeScoreKeyItems(
        EmployeeScoreKeyItems.KeyType.BY_WEEK,
        ctx.ruleSetting().getRuleName(),
        ctx.employee().getEmployeeId(),
        null, null, ctx.weekNo(), null
    );
    return List.of(res);
})

完整修改后的代码

// 上下文封装类
private record RuleE015Context(RuleSetting ruleSetting, Employee employee, Integer weekNo, Long totalDuration) {}

return constraintFactory.forEach(RuleSetting.class)
    .filter(ruleSetting -> ruleSetting.getRuleName().equals("E015") && ruleSetting.getIsActive())
    .join(Shift.class)
    .join(ForeignerType.class)
    .filter((ruleSetting, shift, foreignerType) -> shift.getEmployee().getForeignerType() != null
            && foreignerType.getForeignerType().equals(shift.getEmployee().getForeignerType())
            && shift.getWeekNo() != null)
    .groupBy((ruleSetting, shift, foreignerType) -> ruleSetting,
            (ruleSetting, shift, foreignerType) -> shift.getEmployee(),
            (ruleSetting, shift, foreignerType) -> shift.getWeekNo(),
            ConstraintCollectors.sumLong((ruleSetting, shift, foreignerType) -> shift.getWorkMinutes()))
    .filter((ruleSetting, employee, weekNo, totalDuration) -> totalDuration > employee.getContracts().getMaxMinutesPerWeek())
    // 封装上下文传递数据
    .map((ruleSetting, employee, weekNo, totalDuration) -> new RuleE015Context(ruleSetting, employee, weekNo, totalDuration))
    // 正确关联ForeignerType
    .join(ForeignerType.class,
            (context) -> context.employee().getForeignerType(),
            (foreignerType) -> foreignerType.getForeignerType())
    // 计算惩罚值并提升基数至5
    .penalizeConfigurable((context, foreignerType) -> {
        RuleSetting ruleSetting = context.ruleSetting();
        Employee employee = context.employee();
        Long totalDuration = context.totalDuration();
        
        double ratio = (double) totalDuration / employee.getContracts().getMaxMinutesPerWeek();
        double penalty = Math.abs(ratio) * Math.abs(ruleSetting.getWeight()) * 5;
        return penalty.intValue();
    })
    // 生成惩罚标识
    .indictWith((context, foreignerType) -> {
        RuleE015Context ctx = (RuleE015Context) context;
        EmployeeScoreKeyItems res = new EmployeeScoreKeyItems(
                EmployeeScoreKeyItems.KeyType.BY_WEEK,
                ctx.ruleSetting().getRuleName(),
                ctx.employee().getEmployeeId(),
                null, null, ctx.weekNo(), null
        );
        return List.of(res);
    })
    .asConstraint("E015");

关键说明

  • 用RuleE015Context统一封装所有需要传递的数据,解决下游无法获取上游多参数的问题
  • join时添加关联条件,避免无意义的笛卡尔积,提升规则执行效率
  • 在penalizeConfigurable中通过上下文对象直接获取所需数据,乘以5实现基数提升要求

内容的提问来源于stack exchange,提问作者I. Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 11:39:56