SchedulePlanServiceImpl.java 11.5 KB
package com.bsth.service.schedule.impl;

import com.bsth.entity.Business;
import com.bsth.entity.Line;
import com.bsth.entity.schedule.*;
import com.bsth.entity.schedule.rule.ScheduleRule1Flat;
import com.bsth.repository.schedule.SchedulePlanInfoRepository;
import com.bsth.repository.schedule.SchedulePlanRepository;
import com.bsth.service.BusinessService;
import com.bsth.service.LineService;
import com.bsth.service.schedule.SchedulePlanService;
import com.bsth.service.schedule.TTInfoDetailService;
import com.bsth.service.schedule.TTInfoService;
import com.bsth.service.schedule.rules.shiftloop.ScheduleCalcuParam_input;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResult_output;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResults_output;
import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input;
import com.bsth.service.schedule.rules.strategy.IStrategy;
import com.bsth.service.schedule.rules.ttinfo2.CalcuParam;
import com.bsth.service.schedule.rules.ttinfo2.Result;
import com.google.common.collect.Multimap;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by xu on 16/6/16.
 */
@Service
public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> implements SchedulePlanService {
    @Autowired
    private KieBase kieBase;
    @Autowired
    private IStrategy strategy;
    @Autowired
    private SchedulePlanRepository schedulePlanRepository;
    @Autowired
    private SchedulePlanInfoRepository schedulePlanInfoRepository;
    @Autowired
    private LineService lineService;
    @Autowired
    private TTInfoService ttInfoService;
    @Autowired
    private TTInfoDetailService ttInfoDetailService;
    @Autowired
    private BusinessService businessService;

    /** 日志记录器 */
    private Logger logger = LoggerFactory.getLogger(SchedulePlanServiceImpl.class);

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public SchedulePlan save(SchedulePlan schedulePlan) {
        // 1-1、查找线路具体信息
        Line xl = strategy.getLine(schedulePlan.getXl().getId());
        // 1-2、查出指定线路的所有规则
        TTInfo ttInfo = strategy.getTTInfo(xl.getId()).get(0); // 时刻表id
        schedulePlan.setTtInfo(ttInfo); // TODO:关联的时刻表,之后改掉

        // 2-1、构造drools规则输入数据,输出数据
        // 全局计算参数
        ScheduleCalcuParam_input scheduleCalcuParam_input = new ScheduleCalcuParam_input(schedulePlan);
        // 每个规则对应的输入参数
        List<ScheduleRule_input> scheduleRule_inputs = new ArrayList<>();
        Iterator<ScheduleRule1Flat> scheduleRule1FlatIterator = strategy.getScheduleRule(xl.getId()).iterator();
        while (scheduleRule1FlatIterator.hasNext()) {
            ScheduleRule1Flat scheduleRule1Flat_temp = scheduleRule1FlatIterator.next();
            ScheduleRule_input scheduleRule_input = new ScheduleRule_input(scheduleRule1Flat_temp);
            scheduleRule_inputs.add(scheduleRule_input);
        }
        // 规则输出数据
        ScheduleResults_output scheduleResults_output = new ScheduleResults_output();

        // 2-2、构造drools session->载入数据->启动规则->计算->销毁session
        // 创建session,内部配置的是stateful
        KieSession session = kieBase.newKieSession();
        // 设置gloable对象,在drl中通过别名使用
        session.setGlobal("scheduleResult", scheduleResults_output);
        session.setGlobal("log", logger); // 设置日志

        // 载入数据
        session.insert(scheduleCalcuParam_input);
        for (ScheduleRule_input scheduleRule_input : scheduleRule_inputs) {
            session.insert(scheduleRule_input);
        }
        // 执行rule
        session.fireAllRules();

        // 执行完毕销毁,有日志的也要关闭
        session.dispose();

        System.out.println(scheduleResults_output.showGuideboardDesc1());

        // 2-3、如果排班的数据之前已经有了,删除之前的数据
        schedulePlanInfoRepository.deleteByXlAndScheduleDateGreaterThanEqualAndScheduleDateLessThanEqual(
                xl.getId(), schedulePlan.getScheduleFromTime(), schedulePlan.getScheduleToTime()
        );

        // 3、根据规则返回,组合最后的输出数据
        // 3-1、根据注入的策略服务,获取原始数据
        Map<Date, Multimap<Long, TTInfoDetail>> gbdTTinfoMaps = strategy.getGuideboardXlTTInfoDetailMaps(
                xl.getId(), schedulePlan.getScheduleFromTime(), schedulePlan.getScheduleToTime());

        Map<Long, CarConfigInfo> carConfigMaps = strategy.getCarConfigMaps(xl.getId()); // 车辆配置对应车辆信息
        Map<Long, EmployeeConfigInfo> employeeConfigMaps = strategy.getEmployeeConfigMaps(xl.getId()); // 人员配置对应的人员信息

        // 3-2、循环规则输出
        Map<Long, String> ttInfoMap = new HashMap<>(); // 时刻表映射,id和名字
        List<SchedulePlanInfo> schedulePlanInfos = new ArrayList<>();
        for (ScheduleResult_output scheduleResult_output : scheduleResults_output.getResults()) {
            // 车辆配置对应的车辆
            CarConfigInfo configInfo = carConfigMaps.get(Long.valueOf(scheduleResult_output.getCarConfigId()));
            // 人员配置对应的人员,这里需要分班处理的
            List<EmployeeConfigInfo> employeeConfigInfoList = new ArrayList<>();
            String[] eids = scheduleResult_output.getEmployeeConfigId().split("-");
            for (String eid : eids) {
                employeeConfigInfoList.add(employeeConfigMaps.get(Long.valueOf(eid)));
            }
            // 排班明细(这个要迭代的)
            Collection<TTInfoDetail> ttInfoDetails_ = gbdTTinfoMaps.get(scheduleResult_output.getSd().toDate()).get(
                    Long.parseLong(scheduleResult_output.getGuideboardId()));
            List<TTInfoDetail> ttInfoDetails = new ArrayList<>(ttInfoDetails_);

            // 排序ttInfoDetails
            Collections.sort(ttInfoDetails, new Comparator<TTInfoDetail>() {
                @Override
                public int compare(TTInfoDetail o1, TTInfoDetail o2) {
                    return o1.getFcno().compareTo(o2.getFcno());
                }
            });

            Boolean isFb = false; // 是否分班
            for (TTInfoDetail ttInfoDetail : ttInfoDetails) {
                if (ttInfoDetail.getIsFB())
                    isFb = ttInfoDetail.getIsFB();

                SchedulePlanInfo schedulePlanInfo = new SchedulePlanInfo(
                        xl,
                        scheduleResult_output,
                        ttInfoDetail,
                        isFb,
                        configInfo,
                        employeeConfigInfoList,
                        schedulePlan);

                // 获取公司,分公司信息
                String gsbm = xl.getCompany();
                String fgsbm = xl.getBrancheCompany();
                Business gs = null;
                Business fgs = null;

                Map<String, Object> param = new HashMap<>();

                if (StringUtils.isNotEmpty(gsbm)) {
                    param.clear();
                    param.put("businessCode_eq", gsbm);
                    Iterator<Business> businessIterator = businessService.list(param).iterator();
                    if (businessIterator.hasNext()) {
                        gs = businessIterator.next();
                    }
                }
                if (StringUtils.isNotEmpty(gsbm) && StringUtils.isNotEmpty(fgsbm)) {
                    param.clear();;
                    param.put("upCode_eq", gsbm);
                    param.put("businessCode_eq", fgsbm);
                    Iterator<Business> businessIterator = businessService.list(param).iterator();
                    if (businessIterator.hasNext()) {
                        fgs = businessIterator.next();
                    }
                }

                if (gs != null) {
                    schedulePlanInfo.setGsBm(gs.getBusinessCode());
                    schedulePlanInfo.setGsName(gs.getBusinessName());
                }
                if (fgs != null) {
                    schedulePlanInfo.setFgsBm(fgs.getBusinessCode());
                    schedulePlanInfo.setFgsName(fgs.getBusinessName());
                }

                // 操作人,操作时间
                schedulePlanInfo.setCreateBy(schedulePlan.getCreateBy());
                schedulePlanInfo.setCreateDate(schedulePlan.getCreateDate());
                schedulePlanInfo.setUpdateBy(schedulePlan.getUpdateBy());
                schedulePlanInfo.setUpdateDate(schedulePlan.getUpdateDate());

                schedulePlanInfos.add(schedulePlanInfo);
                ttInfoMap.put(ttInfoDetail.getTtinfo().getId(), ttInfoDetail.getTtinfo().getName());

            }
        }

        schedulePlan.setTtInfoId(StringUtils.join(ttInfoMap.keySet(), ","));
        schedulePlan.setTtInfoNames(StringUtils.join(ttInfoMap.values(), ","));

        // 3-2、保存生成的排班和明细
        schedulePlan.getSchedulePlanInfoList().addAll(schedulePlanInfos); // 关联的排班明细信息
        super.save(schedulePlan);

        return new SchedulePlan();
    }

    @Override
    public SchedulePlan findSchedulePlanTommorw() {
        DateTime today = new DateTime(new Date());
        DateTime tommorw = new DateTime(today.getYear(), today.getMonthOfYear(), today.getDayOfMonth(), 0, 0).plusDays(1);
        Map<String, Object> param = new HashMap<>();
        param.put("scheduleFromTime_le", tommorw.toDate());
        param.put("scheduleToTime_ge", tommorw.toDate()     );
        Iterator<SchedulePlan> schedulePlanIterator = this.list(param).iterator();
        if (schedulePlanIterator.hasNext()) {
            return schedulePlanIterator.next();
        }
        return null;
    }

    @Override
    public Result validateTTInfo(Integer xlid, Date from, Date to) {
        // 构造drools session->载入数据->启动规则->计算->销毁session
        // 创建session,内部配置的是stateful
        KieSession session = kieBase.newKieSession();
        // 设置gloable对象,在drl中通过别名使用
        session.setGlobal("log", logger);
        session.setGlobal("lineService", lineService);
        session.setGlobal("ttInfoDetailService", ttInfoDetailService);

        Result rs = new Result(); // 输出gloable对象
        session.setGlobal("rs", rs);

        // 载入数据
        CalcuParam calcuParam = new CalcuParam(
                new DateTime(from), new DateTime(to), xlid);
        session.insert(calcuParam);
        List<TTInfo> ttInfos = ttInfoService.findAll();
        for (TTInfo ttInfo: ttInfos)
                session.insert(ttInfo);


        // 执行rule
        session.fireAllRules();

        // 执行完毕销毁,有日志的也要关闭
        session.dispose();


        return rs;
    }
}