shiftloop_fb_2.drl 11 KB
package com.bsth.service.schedule.shiftloop;

import org.joda.time.*;
import java.util.*;

import com.bsth.service.schedule.rules.ttinfo.LpInfoResult_output;

import com.bsth.service.schedule.rules.shiftloop.ScheduleCalcuParam_input;
import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResult_output;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResults_output;

import com.bsth.entity.schedule.temp.SchedulePlanRuleResult;

import org.slf4j.Logger;

global Logger log;
global ScheduleResults_output scheduleResult;

/*
    存在(翻班格式)
*/

//------------------------- 第一阶段、计算规则准备数据(天数) ----------------------------//

declare Calcu_days_result_pre
    ruleId: String // 规则Id

    calcu_index_lp : Integer // 计算之后路牌的起始索引
    calcu_index_ry : Integer // 计算之后人员的起始索引

    // 1、第一部分循环需要用到的数据(当开始日期大于启用日期的时候才有)
    calcu_start_date_1: DateTime // 第一部分开始计算日期
    calcu_end_date_1: DateTime // 第一部分结束计算日期

    // 2、第二部分循环需要用到的数据
    sdays : Integer // 总共需要排班的天数
    calcu_start_date_2 : DateTime // 开始计算日期
    calcu_end_date_2 : DateTime // 结束计算日期

end

/*
    计算启用日期,开始计算日期,结束计算日期,相差天数
    1、规则启用日期小于开始计算日期
    2、规则启用日期大于等于开始日期,小于等于结束日期
*/
// 1、启用日期 < 开始日期
rule "calcu_days_1_"
    salience 1000
    when
        ScheduleCalcuParam_input(
            fromDate.isBefore(toDate) || fromDate.isEqual(toDate),
            $fromDate : fromDate,
            $toDate : toDate
        )
        ScheduleRule_input(
            $ruleId : ruleId, $qyrq : qyrq,
            $lpindex : startGbdIndex, $ryindex: startEIndex)
        eval($qyrq.isBefore($fromDate))
    then
        // 构造Calcu_days_result_pre,用于路牌
        Calcu_days_result_pre cdrp = new Calcu_days_result_pre();
        cdrp.setRuleId($ruleId);
        cdrp.setCalcu_index_lp($lpindex);
        cdrp.setCalcu_index_ry($ryindex);
        cdrp.setCalcu_start_date_1($qyrq);
        cdrp.setCalcu_end_date_1($fromDate);
        Period p2 = new Period($fromDate, $toDate, PeriodType.days());
        cdrp.setSdays(p2.getDays() + 1);
        cdrp.setCalcu_start_date_2($fromDate);
        cdrp.setCalcu_end_date_2($toDate);

        insert(cdrp);

        log.info("总共需要排班的天数 sdays={} ruleId={} from={} to={}", (p2.getDays() + 1), $ruleId, $fromDate, $toDate);

end

// 启用日期 属于 [开始日期,结束日期]
rule "calcu_days_2_"
    salience 1000
    when
        ScheduleCalcuParam_input(
            fromDate.isBefore(toDate) || fromDate.isEqual(toDate),
            $fromDate : fromDate,
            $toDate : toDate
        )
        ScheduleRule_input(
            $ruleId : ruleId, $qyrq : qyrq,
            $lpindex : startGbdIndex, $ryindex: startEIndex)
        eval((!$qyrq.isBefore($fromDate)) && (!$qyrq.isAfter($toDate)))
    then
        // 构造Calcu_days_result_pre,用于路牌
        Calcu_days_result_pre cdrp = new Calcu_days_result_pre();
        cdrp.setRuleId($ruleId);
        cdrp.setCalcu_index_lp($lpindex);
        cdrp.setCalcu_index_ry($ryindex);
        cdrp.setCalcu_start_date_1($qyrq);
        cdrp.setCalcu_end_date_1($qyrq);
        Period p2 = new Period($qyrq, $toDate, PeriodType.days());
        cdrp.setSdays(p2.getDays() + 1);
        cdrp.setCalcu_start_date_2($qyrq);
        cdrp.setCalcu_end_date_2($toDate);

        insert(cdrp);

        log.info("总共需要排班的天数 sdays={} ruleId={} from={} to={}", (p2.getDays() + 1), $ruleId, $qyrq, $toDate);

end

//------------------------- 第二阶段、计算规则准备数据2(第一组循环) ----------------------------//
rule "Calcu_loop1_1_" // 路牌在时刻表中存在,就翻
    salience 900
    when
        $cdrp: Calcu_days_result_pre(
            calcu_start_date_1.isBefore(calcu_end_date_1),
            $csd1: calcu_start_date_1,
            $ced1: calcu_end_date_1,
            $ruleId: ruleId,
            $lpindex: calcu_index_lp,
            $ryindex: calcu_index_ry
        )
        $sri: ScheduleRule_input(
            ruleId == $ruleId,
            $gids: guideboardIds,
            $lprangesize : guideboardIds.size(),
            $ryrangesize: employeeConfigIds.size()
        )
        $liro: LpInfoResult_output(
            dateTime.isEqual($csd1),
            $gids.get($lpindex) == lpId,
            $lpId: lpId
        )
    then
        $cdrp.setCalcu_index_lp(($lpindex + 1) % $lprangesize);
        $cdrp.setCalcu_index_ry(($ryindex + 1) % $ryrangesize);
        $cdrp.setCalcu_start_date_1($csd1.plusDays(1));

        log.info("Calcu_loop1_1_ ruleId={}, calcu_index_lp/ry={}/{}",
            $ruleId, $cdrp.getCalcu_index_lp(), $cdrp.getCalcu_index_ry());

        update($cdrp);
end

rule "Calcu_loop1_2_" // 路牌在时刻表中不存在,就不翻
    salience 900
    when
        $cdrp: Calcu_days_result_pre(
            calcu_start_date_1.isBefore(calcu_end_date_1),
            $csd1: calcu_start_date_1,
            $ced1: calcu_end_date_1,
            $ruleId: ruleId
        )
        $sri: ScheduleRule_input(
            ruleId == $ruleId,
            $rangesize : guideboardIds.size()
        )
    then
        $cdrp.setCalcu_start_date_1($csd1.plusDays(1));

        log.info("Calcu_loop1_2_ ruleId={}, calcu_index_lp/ry={}/{}",
            $ruleId, $cdrp.getCalcu_index_lp(), $cdrp.getCalcu_index_ry());

        update($cdrp);
end

//------------------------- 第三阶段、计算规则准备数据2(第二组循环) ----------------------------//
rule "Calcu_loop2_1_" // 路牌在时刻表中存在,就翻
    salience 800
    when
        ScheduleCalcuParam_input($sp: schedulePlan)
        $cdrp: Calcu_days_result_pre(
            calcu_start_date_1.isEqual(calcu_end_date_1),
            calcu_start_date_2.isBefore(calcu_end_date_2) || calcu_start_date_2.isEqual(calcu_end_date_2),
            $csd2: calcu_start_date_2,
            $ced2: calcu_end_date_2,
            $ruleId: ruleId,
            $lpindex: calcu_index_lp,
            $ryindex: calcu_index_ry
        )
        $sri: ScheduleRule_input(
            ruleId == $ruleId,
            $cid: carConfigId,
            $gids: guideboardIds,
            $eids: employeeConfigIds,
            $lprangesize : guideboardIds.size(),
            $ryrangesize: employeeConfigIds.size(),
            $srf: self
        )
        $liro: LpInfoResult_output(
            dateTime.isEqual($csd2),
            $gids.get($lpindex) == lpId,
            $lpId: lpId
        )
    then
        ScheduleResult_output ro = new ScheduleResult_output();
        ro.setRuleId($ruleId);
        ro.setSd($csd2);
        ro.setGuideboardId(String.valueOf($gids.get($lpindex)));
        ro.setEmployeeConfigId(String.valueOf($eids.get($ryindex)));
        ro.setCarConfigId($cid);

        scheduleResult.getResults().add(ro);

        $cdrp.setCalcu_index_lp(($lpindex + 1) % $lprangesize);
        $cdrp.setCalcu_index_ry(($ryindex + 1) % $ryrangesize);
        $cdrp.setCalcu_start_date_2($csd2.plusDays(1));

        // 保存排班规则循环结果 --> SchedulePlanRuleResult
        SchedulePlanRuleResult schedulePlanRuleResult = new SchedulePlanRuleResult($sp);
        schedulePlanRuleResult.setXlId(String.valueOf($srf.getXl().getId()));
        schedulePlanRuleResult.setXlName($srf.getXl().getName());
        schedulePlanRuleResult.setRuleId($ruleId);
        schedulePlanRuleResult.setCcId($cid);
        schedulePlanRuleResult.setCcZbh($srf.getCarConfigInfo().getCl().getInsideCode());
        schedulePlanRuleResult.setGids($srf.getLpIds());
        schedulePlanRuleResult.setGnames($srf.getLpNames());
        schedulePlanRuleResult.setGidindex(String.valueOf($lpindex));
        schedulePlanRuleResult.setEcids($srf.getRyConfigIds());
        schedulePlanRuleResult.setEcdbbms($srf.getRyDbbms());
        schedulePlanRuleResult.setEcindex(String.valueOf($ryindex));
        schedulePlanRuleResult.setScheduleDate($csd2.toDate());

        scheduleResult.getSchedulePlanRuleResults().add(schedulePlanRuleResult);


        log.info("Calcu_loop2_1_ ruleId={}, calcu_index_lp/ry={}/{}, from={}, to={}",
            $ruleId, $cdrp.getCalcu_index_lp(), $cdrp.getCalcu_index_ry(), $csd2, $ced2);

        update($cdrp);
end

rule "Calcu_loop2_2_" // 路牌在时刻表中不存在,就不翻
    salience 800
    when
        ScheduleCalcuParam_input($sp: schedulePlan)
        $cdrp: Calcu_days_result_pre(
            calcu_start_date_1.isEqual(calcu_end_date_1),
            calcu_start_date_2.isBefore(calcu_end_date_2) || calcu_start_date_2.isEqual(calcu_end_date_2),
            $csd2: calcu_start_date_2,
            $ced2: calcu_end_date_2,
            $ruleId: ruleId,
            $lpindex: calcu_index_lp,
            $ryindex: calcu_index_ry
        )
        $sri: ScheduleRule_input(
            ruleId == $ruleId,
            $cid: carConfigId,
            $gids: guideboardIds,
            $eids: employeeConfigIds,
            $srf: self
        )
    then
        ScheduleResult_output ro = new ScheduleResult_output();
        ro.setRuleId($ruleId);
        ro.setSd($csd2);
        ro.setGuideboardId(String.valueOf($gids.get($lpindex)));
        ro.setEmployeeConfigId(String.valueOf($eids.get($ryindex)));
        ro.setCarConfigId($cid);

        scheduleResult.getResults().add(ro);

        $cdrp.setCalcu_start_date_2($csd2.plusDays(1));

        // 保存排班规则循环结果 --> SchedulePlanRuleResult
        SchedulePlanRuleResult schedulePlanRuleResult = new SchedulePlanRuleResult($sp);
        schedulePlanRuleResult.setXlId(String.valueOf($srf.getXl().getId()));
        schedulePlanRuleResult.setXlName($srf.getXl().getName());
        schedulePlanRuleResult.setRuleId($ruleId);
        schedulePlanRuleResult.setCcId($cid);
        schedulePlanRuleResult.setCcZbh($srf.getCarConfigInfo().getCl().getInsideCode());
        schedulePlanRuleResult.setGids($srf.getLpIds());
        schedulePlanRuleResult.setGnames($srf.getLpNames());
        schedulePlanRuleResult.setGidindex(String.valueOf($lpindex));
        schedulePlanRuleResult.setEcids($srf.getRyConfigIds());
        schedulePlanRuleResult.setEcdbbms($srf.getRyDbbms());
        schedulePlanRuleResult.setEcindex(String.valueOf($ryindex));
        schedulePlanRuleResult.setScheduleDate($csd2.toDate());

        scheduleResult.getSchedulePlanRuleResults().add(schedulePlanRuleResult);

        log.info("Calcu_loop2_2_ ruleId={}, calcu_index_lp/ry={}/{}, from={}, to={}",
            $ruleId, $cdrp.getCalcu_index_lp(), $cdrp.getCalcu_index_ry(), $csd2, $ced2);

        update($cdrp);
end