shiftloop_fb_2.drl 14.7 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.utils.Md5Util;

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 com.bsth.service.schedule.rules.ScheduleRuleService;

import org.slf4j.Logger;

global Logger log;
global ScheduleResults_output scheduleResult;
global ScheduleRuleService scheduleRuleService;

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

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

declare Calcu_days_result_pre
    ruleId: String // 规则Id
    ruleMd5: String // 规则md5

    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,
            $xlId: xlId
        )
        ScheduleRule_input(
            $ruleId : ruleId, $qyrq : qyrq, $ruleMd5: ruleMd5,
            $lpindex : startGbdIndex, $ryindex: startEIndex)
        eval($qyrq.isBefore($fromDate))
    then
        scheduleResult.setXlid($xlId);

        // 构造Calcu_days_result_pre,用于路牌
        Calcu_days_result_pre cdrp = new Calcu_days_result_pre();
        cdrp.setRuleId($ruleId);
        cdrp.setRuleMd5($ruleMd5);
        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,
            $xlId: xlId
        )
        ScheduleRule_input(
            $ruleId : ruleId, $qyrq : qyrq, $ruleMd5: ruleMd5,
            $lpindex : startGbdIndex, $ryindex: startEIndex)
        eval((!$qyrq.isBefore($fromDate)) && (!$qyrq.isAfter($toDate)))
    then
        scheduleResult.setXlid($xlId);

        // 构造Calcu_days_result_pre,用于路牌
        Calcu_days_result_pre cdrp = new Calcu_days_result_pre();
        cdrp.setRuleId($ruleId);
        cdrp.setRuleMd5($ruleMd5);
        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

// 使用已经排过班的数据修正Calcu_days_result_pre
// 1、避免每次从规则的启用日期开始算
// 2、时刻表会不停的修正,如果每次都从规则启用日期开始算,会出错

declare SchedulePlanRuleResult_wrap
    ruleId: String // 规则Id
    ruleMd5: String // 规则md5编码
    scheduleDate: DateTime // 排班日期

    isUsed: Boolean = false // 是否被使用过

    self: SchedulePlanRuleResult; // 原始对象数据
end

rule "Calcu_SchedulePlanRuleResult_wrap"
    salience 950
    when
        ScheduleCalcuParam_input(
            fromDate.isBefore(toDate) || fromDate.isEqual(toDate),
            $fromDate : fromDate,
            $toDate : toDate,
            $xlId: xlId,
            $self: schedulePlan
        )
        eval($self.getIsHistoryPlanFirst() == true) // 是否使用历史排班标识
        $sprr: SchedulePlanRuleResult($qyrq: qyrq) from scheduleRuleService.findLastByXl($xlId, $fromDate.toDate())

    then
        // 创建班序历史结果数据
        SchedulePlanRuleResult_wrap schedulePlanRuleResult_wrap = new SchedulePlanRuleResult_wrap();
        schedulePlanRuleResult_wrap.setRuleId($sprr.getRuleId());
        schedulePlanRuleResult_wrap.setScheduleDate(new DateTime($sprr.getScheduleDate()));
        schedulePlanRuleResult_wrap.setSelf($sprr);

        // 规则Md5编码
        String md5 = Md5Util.getMd5(
            String.valueOf($qyrq.getTime()) + "_" +
            $sprr.getGids() + "_" + $sprr.getEcids()
        );

//        System.out.println("修改后的md5:" + md5 + "车辆:" + $sprr.getCcZbh());

        schedulePlanRuleResult_wrap.setRuleMd5(md5);

        insert(schedulePlanRuleResult_wrap);
end


// 1、启用日期 < 开始日期
// 2、如果最近的排班规则历史时间在 (启用日期,开始日期) 之间,需要重新修正预处理数据
rule "calcu_days_1_with_result"
    no-loop
    salience 960
    when
        $cdrp: Calcu_days_result_pre(
            calcu_start_date_1.isBefore(calcu_start_date_2),
            $ruleId: ruleId,
            $ruleMd5: ruleMd5
        )
        $srrr_wrap: SchedulePlanRuleResult_wrap(
//            ruleId == $ruleId,
            ruleMd5 == $ruleMd5,
            scheduleDate.isAfter($cdrp.calcu_start_date_1),
            scheduleDate.isBefore($cdrp.calcu_start_date_2),
            isUsed == false,
            $scheduleDate: scheduleDate,
            $self: self
        )
    then
        // 修正排班数据
//        log.info("准备修正 ruleId={} historyDate={}", $ruleId, $scheduleDate);

        $cdrp.setCalcu_index_lp(Integer.valueOf($self.getGidindex()));
        $cdrp.setCalcu_index_ry(Integer.valueOf($self.getEcindex()));
        $cdrp.setCalcu_start_date_1($scheduleDate);
        update($cdrp);

        $srrr_wrap.setIsUsed(true);
        update($srrr_wrap);

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, $xlid: xlId)
        $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,
            $ttinfoId: ttInfoId,
            $ttinfoName: ttInfoName
        )
    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);
        ro.setXlId($xlid);

        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.setXlId($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());
        schedulePlanRuleResult.setTtinfoId($ttinfoId);
        schedulePlanRuleResult.setTtinfoName($ttinfoName);

        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, $xlid: xlId)
        $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);
        ro.setXlId($xlid);

        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