Arrival2Schedule.java 6.16 KB
package com.bsth.data.match;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.bsth.data.arrival.ArrivalComparator;
import com.bsth.data.arrival.ArrivalData_GPS;
import com.bsth.data.arrival.ArrivalEntity;
import com.bsth.data.schedule.DayOfSchedule;
import com.bsth.data.schedule.ScheduleComparator;
import com.bsth.entity.realcontrol.ScheduleRealInfo;
import com.bsth.service.directive.DirectiveService;
import com.bsth.websocket.handler.SendUtils;

@Component
public class Arrival2Schedule implements ApplicationContextAware {
	
	private static DayOfSchedule dayOfSchedule;
	
	
	private static ScheduleComparator.FCSJ schComparator;
	private static ArrivalComparator arrComparator;
	private static MatchResultComparator mrComparator;;
	private static SendUtils sendUtils;
	private static DirectiveService directiveService;
	private final static int ONE_MINUTE = 1000 * 60;
	//定一个4小时的范围,基本能对正常班次进行容错。主要防止早上停车场GPS飘导致完成晚上的进场班次
	private final static int FOUR_HOURS = 1000 * 60 * 60 * 4;
	
	static{
		schComparator = new ScheduleComparator.FCSJ();
		arrComparator = new ArrivalComparator();
		mrComparator = new MatchResultComparator();
	}
	
	/**
	 * 
	 * @Title: start 
	 * @Description: TODO(开始) 
	 * @param @param cars    需要匹配的车辆集合
	 */
	public static void start(Set<String> cars){
		
		for(String car : cars){
			new SchMatchThread(car).start();
		}
	}
	
	public static class SchMatchThread extends Thread{
		String nbbm;
		public SchMatchThread(String nbbm){
			this.nbbm = nbbm;
		}
		@Override
		public void run() {
			//班次列表
			List<ScheduleRealInfo> schList = dayOfSchedule.findByNbbm(nbbm);
			//进出起终点数据
			List<ArrivalEntity> arrList = ArrivalData_GPS.findByNbbm(nbbm);
			//排序
			Collections.sort(schList, schComparator);
			Collections.sort(arrList, arrComparator);
			
			//用实际来匹配计划
			for(ArrivalEntity arr : arrList){
				match(arr, schList);
			}
		}
		private void match(ArrivalEntity arr, List<ScheduleRealInfo> schList) {
			schList = matchFilter(schList);
			
			if(arr.getInOut() == 1)
				matchOut(arr, schList);
			else if(arr.getInOut() == 0)
				matchIn(arr, schList);
		}
		
		private List<ScheduleRealInfo> matchFilter(List<ScheduleRealInfo> schList) {
			List<ScheduleRealInfo> list = new ArrayList<>();
			for(ScheduleRealInfo sch : schList){
				//烂班不匹配
				if(sch.isDestroy())
					continue;
				
				//没有里程的不匹配
				if(sch.getBcsj() == null && sch.getJhlc() == null)
					continue;
				
				list.add(sch);
			}
			return list;
		}
		
		private void matchOut(ArrivalEntity arr, List<ScheduleRealInfo> schList){
			List<MatchResult> mrs = new ArrayList<>();
			ScheduleRealInfo sch;
			MatchResult mr;
			for(int i = 0; i < schList.size(); i ++){
				sch = schList.get(i);
				if(!arr.isTcc() && arr.getUpDown() != Integer.parseInt(sch.getXlDir()))
					continue;
				
				if(!arr.getStopNo().equals(sch.getQdzCode()))
					continue;
				
				//班次有实发时间
				if(sch.getFcsjActualTime() != null){
					//实际发车已经被引用
					if(Math.abs(arr.getTs() - sch.getFcsjActualTime()) < ONE_MINUTE)
						return;
					else
						continue;
				}
				//添加一个匹配结果
				mr = new MatchResult();
				mr.sch = sch;
				mr.ts = arr.getTs();
				mr.diff = arr.getTs() - sch.getFcsjT();
				mr.success = dayOfSchedule.validStartTime(sch, arr.getTs());
				
				if(Math.abs(mr.diff) < FOUR_HOURS && mr.success)
					mrs.add(mr);
			}
			
			if(mrs.size() > 0){
				//排序后的第一个 就是最合适的匹配
				Collections.sort(mrs, mrComparator);
				mr = mrs.get(0);
				
				mr.sch.setFcsjActualAll(mr.ts);
				//通知客户端
				sendUtils.sendFcsj(mr.sch);
				//持久化
				dayOfSchedule.save(mr.sch);
			}
		}
		
		private void matchIn(ArrivalEntity inArr, List<ScheduleRealInfo> schList){
			
			List<MatchResult> mrs = new ArrayList<>();
			ScheduleRealInfo sch;
			MatchResult mr;
			for(int i = 0; i < schList.size(); i ++){
				sch = schList.get(i);
				if(!inArr.isTcc() && inArr.getUpDown() != Integer.parseInt(sch.getXlDir()))
					continue;
				
				if(!inArr.getStopNo().equals(sch.getZdzCode()))
					continue;
				
				//班次有实达时间
				if(sch.getZdsjActualTime() != null){
					//实际到达已经被引用
					if(Math.abs(inArr.getTs() - sch.getZdsjActualTime()) < ONE_MINUTE)
						return;
					else
						continue;
				}
				
				//添加一个匹配结果
				mr = new MatchResult();
				mr.sch = sch;
				mr.ts = inArr.getTs();
				mr.diff = inArr.getTs() - sch.getZdsjT();
				mr.success = dayOfSchedule.validEndTime(sch, inArr.getTs());
				if(Math.abs(mr.diff) < FOUR_HOURS && mr.success)
					mrs.add(mr);
			}
			
			if(mrs.size() > 0){
				//排序后的第一个 就是最合适的匹配
				Collections.sort(mrs, mrComparator);
				mr = mrs.get(0);
				mr.sch.setZdsjActualAll(mr.ts);
				
				int doneSum = dayOfSchedule.doneSum(mr.sch.getClZbh());
				ScheduleRealInfo next = dayOfSchedule.next(mr.sch);
				if(null != next){
					next.setQdzArrDateSJ(mr.sch.getZdsjActual());
					//下发调度指令
					directiveService.send60Dispatch(next, doneSum, "系统");
				}
				else//下发文本指令(已结束运营)
					directiveService.send60Phrase(nbbm, "到达终点 " + mr.sch.getZdzName() + ",已完成当日所有排班。", "系统");
				//通知客户端
				sendUtils.sendZdsj(mr.sch, next, doneSum);
				//持久化
				dayOfSchedule.save(mr.sch);
			}
		}
	}
	
	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		sendUtils = arg0.getBean(SendUtils.class);
		dayOfSchedule = arg0.getBean(DayOfSchedule.class);
		directiveService = arg0.getBean(DirectiveService.class);
	}
}