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

import com.bsth.data.gpsdata_v2.entity.StationRoute;
import com.bsth.entity.Line;
import com.bsth.entity.schedule.SchedulePlan;
import com.bsth.entity.schedule.TTInfo;
import com.bsth.repository.BusinessRepository;
import com.bsth.repository.LineRepository;
import com.bsth.repository.schedule.*;
import com.bsth.service.schedule.SchedulePlanService;
import com.bsth.service.schedule.exception.ScheduleException;
import com.bsth.service.schedule.impl.plan.kBase3.validate.rule.ValidateRuleResult;
import com.bsth.service.schedule.impl.plan.kBase3.validate.timetable.CalcuParam;
import com.bsth.service.schedule.impl.plan.kBase3.validate.timetable.Result;
import com.bsth.service.schedule.impl.plan.DroolsSchedulePlan;
import com.bsth.service.schedule.impl.plan.ScheduleRuleService;
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.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by xu on 16/6/16.
 */
@Service
public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> implements SchedulePlanService {
    @Autowired
    @Qualifier("coreKBase")
    private KieBase coreKBase;

    @Autowired
    @Qualifier("preKBase")
    private KieBase preKBase;

    @Autowired
    @Qualifier("KBase3")
    private KieBase validateKBase;

    @Autowired
    private ScheduleRule1FlatRepository scheduleRule1FlatRepository;
    @Autowired
    private TTInfoRepository ttInfoRepository;
    @Autowired
    private TTInfoDetailRepository ttInfoDetailRepository;
    @Autowired
    private LineRepository lineRepository;
    @Autowired
    private CarConfigInfoRepository carConfigInfoRepository;
    @Autowired
    private GuideboardInfoRepository guideboardInfoRepository;
    @Autowired
    private EmployeeConfigInfoRepository employeeConfigInfoRepository;
    @Autowired
    private BusinessRepository businessRepository;
    @Autowired
    private ScheduleRuleService scheduleRuleService;
    @Autowired
    private RerunRuleRepository rerunRuleRepository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

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

    /** 线路独占锁 */
    private ConcurrentHashMap<Integer, ReentrantLock> lineXLatchMaps = new ConcurrentHashMap<>();
    private ReentrantLock getLineXLatch(Integer xlid) {
        ReentrantLock lineXLatch = lineXLatchMaps.get(xlid);
        if (lineXLatch == null) {
            lineXLatch = new ReentrantLock();
            ReentrantLock pre = lineXLatchMaps.putIfAbsent(xlid, lineXLatch);
            if (pre != null) {
                lineXLatch = pre;
            }
        }
        return lineXLatch;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public SchedulePlan save(SchedulePlan schedulePlan) {
        ReentrantLock lineXLatch = getLineXLatch(schedulePlan.getXl().getId());
        try {
            if (lineXLatch.tryLock(1, TimeUnit.SECONDS)) {
                // pre、如果排班的数据之前已经有了,删除之前的数据
                Date startPre = new Date();
                scheduleRuleService.deleteSchedulePlanInfo(
                        schedulePlan.getXl().getLineCode(),
                        schedulePlan.getScheduleFromTime(),
                        schedulePlan.getScheduleToTime());
                Date endPre = new Date();
                logger.info("删除数据 {} ms --->", endPre.getTime() - startPre.getTime());

                // core、生成排班计划
                DroolsSchedulePlan droolsSchedulePlan = new DroolsSchedulePlan(
                        schedulePlan,
                        lineRepository, scheduleRule1FlatRepository,
                        ttInfoRepository, ttInfoDetailRepository,
                        carConfigInfoRepository, employeeConfigInfoRepository,
                        rerunRuleRepository, businessRepository,
                        scheduleRuleService,
                        preKBase, coreKBase,
                        logger
                );
                droolsSchedulePlan.generatePlan();

                return new SchedulePlan();
            } else {
                throw new ScheduleException("当前线路正在排班,请稍后再操作...");
            }
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        } finally {
            try {
                lineXLatch.unlock();
            } catch (Exception exp2) {

            }

        }

    }

    @Override
    public void delete(Long aLong) throws ScheduleException {
        scheduleRuleService.deleteSchedulePlanAll(aLong);
    }

    @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 = validateKBase.newKieSession();
        // 设置gloable对象,在drl中通过别名使用
        session.setGlobal("log", logger);
        session.setGlobal("tTInfoDetailRepository", ttInfoDetailRepository);

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

        // 载入数据
        Line line = lineRepository.findOne(xlid);
        session.insert(line);

        CalcuParam calcuParam = new CalcuParam(
                new DateTime(from), new DateTime(to), xlid);
        session.insert(calcuParam);
        List<TTInfo> ttInfos = ttInfoRepository.findByXlId(xlid);
        for (TTInfo ttInfo: ttInfos) {
            session.insert(ttInfo);
        }

        // 执行rule
        session.fireAllRules();

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

        return rs;
    }

    @Override
    public ValidateRuleResult validateRule(Integer xlId, Date from, Date to) {
        KieSession session = validateKBase.newKieSession();
        session.setGlobal("LOG", logger);
        session.setGlobal("ccRepo", carConfigInfoRepository);
        session.setGlobal("lpRepo", guideboardInfoRepository);
        session.setGlobal("ecRepo", employeeConfigInfoRepository);
        session.setGlobal("ruleRepo", scheduleRule1FlatRepository);

        ValidateRuleResult result = new ValidateRuleResult();
        session.setGlobal("result", result);

        com.bsth.service.schedule.impl.plan.kBase3.validate.rule.CalcuParam calcuParam =
                new com.bsth.service.schedule.impl.plan.kBase3.validate.rule.CalcuParam();
        calcuParam.setXlId(xlId);
        calcuParam.setFromDate(new DateTime(from));
        calcuParam.setToDate(new DateTime(to));
        session.insert(calcuParam);

        session.fireAllRules();

        session.dispose();;

        return result;
    }


    public Map<String,Object> listwest(Map map){

        SimpleDateFormat sfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String line = map.get("line").toString();
        String page = map.get("page").toString();
        Map<String, Object> modelMap = new HashMap<String, Object>();
        String fgs="";
        if(map.get("fgsdm")!=null){
            fgs=map.get("fgsdm").toString();
        }
        
        String sql ="SELECT sp.xl as xl,MAX(sp.tt_info_names) as tt_info_name, " +
                "MAX(sp.schedule_from_time) as from_time ,MAX(sp.schedule_to_time) as to_time, " +
                "MAX(line.name) as name , MAX(us.user_name) as uname, " +
                "MAX(sp.update_date) as updata_date,max(bu.business_name) as business_name  " +
                "from bsth_c_s_sp sp " +
                "LEFT JOIN bsth_c_line  line on sp.xl = line.line_code   " +
                "left join bsth_c_sys_user us  on sp.update_by = us.id " +
                "LEFT JOIN bsth_c_business bu on line.branche_company = bu.business_code " +
                "where line.name not like '%测试线路%' and sfyy = '1' " +
                "and line.destroy = '0' " ;
        if(!fgs.equals(" ") && !fgs.equals("")){
            sql +=" and line.branche_company = '"+fgs+"'";
        }
        if(!line.equals(" ") && !line.equals("")){
            sql += "and sp.xl="+line;
        }
         
        sql += " GROUP BY sp.xl ORDER BY MAX(sp.schedule_from_time);";
            List<Map> list = null;
        try {
              list = jdbcTemplate.query(sql, new RowMapper<Map>() {
                @Override
                public Map mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Map map = new HashMap();
                    map.put("xl", rs.getString("xl"));
                    map.put("ttInfoName", rs.getString("tt_info_name"));
                    map.put("fromTime",rs.getDate("from_time"));
                    map.put("toTime", rs.getDate("to_time"));
                    map.put("name", rs.getString("name"));
                    map.put("uName", rs.getString("uname"));
                    map.put("updataDate", rs.getString("updata_date"));
                    map.put("businessName", rs.getString("business_name"));
                    return map;
                }
                
            });
        
            for (Map m : list) {
                m.put("updataDate", sfd.format(sfd.parse(m.get("updataDate").toString())));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
                
        
        //分页
        if(page.length() != 0 ){
            int currPage = Integer.valueOf(page);
            modelMap.put("totalPage", list.size()%10>0?(list.size()/10 + 1):list.size()/10);
//			modelMap.put("dataList", resList.subList(currPage*10,((currPage+1)*10)>=resList.size()?resList.size():(currPage+1)*10));
            modelMap.put("list", list);
        } else {
            modelMap.put("dataList", list);
        }
        
        
        return modelMap;
    }
}