kBase3_validate_timetable.drl 10.7 KB
package com.bsth.service.schedule.impl.plan.kBase3.validate.timetable;

import org.joda.time.*;
import java.util.*;
import org.apache.commons.lang3.StringUtils;

import com.bsth.service.schedule.impl.plan.kBase3.validate.timetable.Result;
import com.bsth.service.schedule.impl.plan.kBase3.validate.timetable.Result.StatInfo;
import com.bsth.service.schedule.impl.plan.kBase3.validate.timetable.CalcuParam;

import com.bsth.entity.schedule.TTInfo;
import com.bsth.entity.schedule.TTInfoDetail;
import com.bsth.entity.Line;

import com.bsth.repository.schedule.TTInfoDetailRepository;

import org.slf4j.Logger
import org.joda.time.format.DateTimeFormat
import java.lang.String
import java.lang.Object;


// 全局日志类(一般使用调用此规则的service类)
global Logger log;
global TTInfoDetailRepository tTInfoDetailRepository;

// 输出
global Result rs;

/*
    规则说明:
    1、找出指定线路,指定时间范围的时刻表
    2、统计这些时刻表班次数据的情况
*/

//-------------- 第一阶段、计算规则迭代数据(天数) ------------//
declare Calcu_iter_days_result
    xlId: Integer // 线路Id
    xlName: String // 线路名字

    // 迭代数据
    calcu_day: Integer // 准备计算第几天
    calcu_weekday: Integer // 准备计算星期几(1到7)
    calcu_date: DateTime // 准备计算的具体日期

    // 范围数据
    calcu_days: Integer // 总共需要计算的天数
    calcu_start_date: DateTime // 开始计算日期
    calcu_end_date: DateTime // 结束计算日期

    // 时刻表映射数据
    ttinfomap: Map // 指定时间段内,用的时刻表id映射 Map<Long, Long>
end

rule "calcu_iter_days"
    salience 1900
    when
        CalcuParam(
            $xlId: xlId,
            $fromDate: fromDate,
            $toDate: toDate,
            $fromDate.isBefore($toDate) || $fromDate.isEqual($toDate)
        )
        $line: Line(id == $xlId)
    then
        // 构造Calcu_iter_days_result对象,进行下一步计算
        Calcu_iter_days_result cidr = new Calcu_iter_days_result();
        Period p = new Period($fromDate, $toDate, PeriodType.days());

        cidr.setXlId($xlId);
        cidr.setXlName($line.getName());

        cidr.setCalcu_day(new Integer(1));
        cidr.setCalcu_weekday(Integer.valueOf($fromDate.getDayOfWeek()));
        cidr.setCalcu_date($fromDate);

        cidr.setCalcu_days(Integer.valueOf(p.getDays() + 1));
        cidr.setCalcu_start_date($fromDate);
        cidr.setCalcu_end_date($toDate);

        cidr.setTtinfomap(new HashMap());

        log.info(
            "线路={}-id={},开始时间={},结束时间={},总共计算的天数={},将从开始时间迭代",
            cidr.getXlName(),
            cidr.getXlId(),
            cidr.getCalcu_start_date(),
            cidr.getCalcu_end_date(),
            cidr.getCalcu_days()
        );

        insert(cidr);
end

//-------------- 第二阶段、包装时刻表实体类到内部对象 ------------//

declare TTInfo_wrap
    id: Long // 时刻表id
    name: String // 时刻表名字
    weekdays: List // 周一到周日是否启用 List<Boolean>
    specialDays: List // 特殊节假日 List<DateTime>
    updateDate: DateTime // 最新修改时间
end

rule "TTInfo_wrap_result"
    salience 900
    when
        CalcuParam($xlId: xlId)
        $ttinfo: TTInfo(
            xl.id == $xlId,
            isEnableDisTemplate == true,
            isCancel == false
        )
    then
        TTInfo_wrap ttInfo_wrap = new TTInfo_wrap();
        ttInfo_wrap.setId($ttinfo.getId());
        ttInfo_wrap.setName($ttinfo.getName());
        ttInfo_wrap.setUpdateDate(new DateTime($ttinfo.getUpdateDate()));
        ttInfo_wrap.setWeekdays(new ArrayList());
        ttInfo_wrap.setSpecialDays(new ArrayList());

        String[] days = $ttinfo.getRule_days().split(",");
        for (int i = 0; i < 7; i++) {
            if ("1".equals(days[i])) {
                ttInfo_wrap.getWeekdays().add(true);
            } else {
                ttInfo_wrap.getWeekdays().add(false);
            }
        }

        if (StringUtils.isNotEmpty($ttinfo.getSpecial_days())) {
            String[] sdays = $ttinfo.getSpecial_days().split(",");
            for (int i = 0; i < sdays.length; i++) {
                ttInfo_wrap.getSpecialDays().add(
                    DateTimeFormat.forPattern(
                        "yyyy-MM-dd").parseDateTime(sdays[i]));
            }
        }

        log.info("时刻表={},id={},常规日期={},特殊日期={}",
            ttInfo_wrap.getName(),
            ttInfo_wrap.getId(),
            ttInfo_wrap.getWeekdays(),
            ttInfo_wrap.getSpecialDays());

        insert(ttInfo_wrap);

end

//-------------- 第三阶段、时刻表的日期匹配 ------------//

declare TTInfoDetails_wrap
    ttInfoId: Long // 时刻表id
    bcInfoList: List // 班次信息列表 List<TTInfoDetail>
end

rule "Calcu_iter_days_special_day" // 特殊日期匹配
    salience 800
    when
        $cid : Calcu_iter_days_result(
            $calcu_date: calcu_date,
            $calcu_day: calcu_day,
            calcu_day <= calcu_days
        )
        TTInfo_wrap(
            $tid: id,
            $tname: name,
            specialDays contains $calcu_date
        )
    then
        // 更新迭代对象
        Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
        $cid.setCalcu_day(new_calcu_day);
        DateTime new_calcu_date = $calcu_date.plusDays(1);
        $cid.setCalcu_date(new_calcu_date);
        $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));

        log.info("启用特殊日期时刻表:" +
            "时刻表id={} 特殊日期={}",
            $tid, $calcu_date);

        // 判定使用的时刻表
        if (!$cid.getTtinfomap().containsKey($tid)) {
            $cid.getTtinfomap().put($tid, $tid);
            StatInfo statInfo = new StatInfo();
            statInfo.setTtid($tid);
            statInfo.setTtname($tname);
            insert(statInfo);

            TTInfoDetails_wrap ttInfoDetails_wrap = new TTInfoDetails_wrap();
            ttInfoDetails_wrap.setTtInfoId($tid);
            ttInfoDetails_wrap.setBcInfoList(tTInfoDetailRepository.findByTtinfoId($tid));
            insert(ttInfoDetails_wrap);
        }
        update($cid);

end

rule "Calcu_iter_days_normal_day" // 平日匹配
    salience 700
    when
        $cid : Calcu_iter_days_result(
            $calcu_date: calcu_date,
            $calcu_weekday: calcu_weekday,
            $calcu_day: calcu_day,
            calcu_day <= calcu_days
        )
        TTInfo_wrap(
            $tid: id,
            $tname: name,
            specialDays not contains $calcu_date,
            weekdays[$calcu_weekday - 1] == Boolean.TRUE
        )
    then
        // 更新迭代对象
        Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
        $cid.setCalcu_day(new_calcu_day);
        DateTime new_calcu_date = $calcu_date.plusDays(1);
        $cid.setCalcu_date(new_calcu_date);
        $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));


        log.info("启用常规日期时刻表:" +
            "时刻表id={} 常规日期={} 星期几={}",
            $tid, $calcu_date, $calcu_weekday);

        // 判定使用的时刻表
        if (!$cid.getTtinfomap().containsKey($tid)) {
            $cid.getTtinfomap().put($tid, $tid);
            StatInfo statInfo = new StatInfo();
            statInfo.setTtid($tid);
            statInfo.setTtname($tname);
            insert(statInfo);

            TTInfoDetails_wrap ttInfoDetails_wrap = new TTInfoDetails_wrap();
            ttInfoDetails_wrap.setTtInfoId($tid);
            ttInfoDetails_wrap.setBcInfoList(tTInfoDetailRepository.findByTtinfoId($tid));
            insert(ttInfoDetails_wrap);
        }
        update($cid);

end

rule "Calcu_iter_days_other_day" // 都没有的情况下,匹配
    salience 500
    when
        $cid : Calcu_iter_days_result(
            $calcu_date: calcu_date,
            $calcu_weekday: calcu_weekday,
            $calcu_day: calcu_day,
            calcu_day <= calcu_days
        )
        TTInfo_wrap(
            $tid: id,
            $tname: name,
            specialDays not contains $calcu_date,
            weekdays[$calcu_weekday - 1] == false
        )
    then
        // 更新迭代对象
        Integer new_calcu_day = Integer.valueOf($calcu_day + 1);
        $cid.setCalcu_day(new_calcu_day);
        DateTime new_calcu_date = $calcu_date.plusDays(1);
        $cid.setCalcu_date(new_calcu_date);
        $cid.setCalcu_weekday(Integer.valueOf(new_calcu_date.getDayOfWeek()));

        log.info("启用默认日期时刻表:" +
            "时刻表id={} 常规日期={} 星期几={}",
            $tid, $calcu_date, $calcu_weekday);

        // 判定使用的时刻表
        if (!$cid.getTtinfomap().containsKey($tid)) {
            $cid.getTtinfomap().put($tid, $tid);
            StatInfo statInfo = new StatInfo();
            statInfo.setTtid($tid);
            statInfo.setTtname($tname);
            insert(statInfo);

            TTInfoDetails_wrap ttInfoDetails_wrap = new TTInfoDetails_wrap();
            ttInfoDetails_wrap.setTtInfoId($tid);
            Map<String, Object> param = new HashMap<String, Object>();
            ttInfoDetails_wrap.setBcInfoList(tTInfoDetailRepository.findByTtinfoId($tid));
            insert(ttInfoDetails_wrap);
        }
        update($cid);

end

//-------------- 第四阶段、时刻表明细统计值 ------------//

rule "statinfo_result" // 统计计算结果
    salience 300
    no-loop
    when
        $statInfo: StatInfo($tid: ttid)
        $ttInfoDetails_wrap: TTInfoDetails_wrap(ttInfoId == $tid)
        $allbc: Long() from accumulate (TTInfoDetail() from $ttInfoDetails_wrap.getBcInfoList(), count())
        $inbc: Long() from accumulate (TTInfoDetail(bcType == "in") from $ttInfoDetails_wrap.getBcInfoList(), count())
        $outbc: Long() from accumulate (TTInfoDetail(bcType == "out") from $ttInfoDetails_wrap.getBcInfoList(), count())
        $yybc: Long() from accumulate (TTInfoDetail(bcType != "out", bcType != "in") from $ttInfoDetails_wrap.getBcInfoList(), count())
        $errorbc: Long() from accumulate ($ttd: TTInfoDetail() from $ttInfoDetails_wrap.getBcInfoList(), ecount($ttd))
    then
        log.info("时刻表={},id={},班次数={},进场={},出场={},营运={},错误={}", $statInfo.getTtname(), $statInfo.getTtid(), $allbc, $inbc, $outbc, $yybc, $errorbc);

        $statInfo.setAllbc($allbc);
        $statInfo.setInbc($inbc);
        $statInfo.setOutbc($outbc);
        $statInfo.setYybc($yybc);
        $statInfo.setErrorbc($errorbc);

        int lineVersion = ((TTInfoDetail) $ttInfoDetails_wrap.getBcInfoList().get(0)).getLineVersion();
        $statInfo.setLineVersion(lineVersion);

        rs.getInfos().add($statInfo);

end