Arrival2Schedule.java 6.41 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;

/**
 * 
 * @ClassName: Arrival2Schedule 
 * @Description: TODO(进出数据匹配班次) 
 * @author PanZhao 
 * @date 2016年8月10日 下午2:26:22 
 *
 */
@Component
public class Arrival2Schedule implements ApplicationContextAware{
	
	private static ScheduleComparator.FCSJ schComparator;
	private static ArrivalComparator arrComparator;
	private static SendUtils sendUtils;
	private static DayOfSchedule dayOfSchedule;
	private static DirectiveService directiveService;
	
	private final static long MAX_RANGE = 1000 * 60 * 60 * 4L;
	
	static{
		schComparator = new ScheduleComparator.FCSJ();
		arrComparator = new ArrivalComparator();
	}
	
	/**
	 * 
	 * @Title: start 
	 * @Description: TODO(开始) 
	 * @param @param cars    需要匹配的车辆集合
	 */
	public static void start(Set<String> cars){
		
		for(String car : cars){
			new GpsMatchThread(car).start();
		}
	}
	
	public static class GpsMatchThread extends Thread{

		String nbbm;
		public GpsMatchThread(String nbbm){
			this.nbbm = nbbm;
		}
		
		@Override
		public void run() {
			//班次列表
			List<ScheduleRealInfo> schList = dayOfSchedule.findByNbbm(nbbm);
			//进出起终点数据
			List<ArrivalEntity> arrList = ArrivalData_GPS.getIncrement(nbbm);
			System.out.println("####匹配进出站增量数据 " + arrList.size());
			//排序
			Collections.sort(schList, schComparator);
			Collections.sort(arrList, arrComparator);
			
			int si = lastMatchPoint(schList);
			int ai = afterByTime(arrList, lastMatchTime(schList.get(si)));
			
			//按起始索引开始匹配
			match(arrList, ai, schList, si);
		}
		
		public void match(List<ArrivalEntity> arrList, int ai, List<ScheduleRealInfo> schList, int si){
			
			int sLen = schList.size();
			for(; si < sLen; si ++)
				match(arrList, ai, schList.get(si));
		}
		
		public void match(List<ArrivalEntity> arrList, int ai, ScheduleRealInfo sch){
			//烂班不参与
			if(sch.isDestroy())
				return;
			
			int aLen = arrList.size();
			
			List<MatchResult> inRsList = new ArrayList<>()
						,outRsList = new ArrayList<>();
			
			MatchResult mrs;
			for(;ai < aLen; ai ++){
				mrs = match(arrList.get(ai), sch);
				if(!mrs.success)
					continue;
				
				if(mrs.inOut == 0)
					inRsList.add(mrs);
				else if(mrs.inOut == 1)
					outRsList.add(mrs);
			}
			
			if(outRsList.size() > 0){
				//排序后的第一个 就是最合适的匹配
				Collections.sort(outRsList, new MatchResultComparator());
				mrs = outRsList.get(0);
				
				mrs.sch.setFcsjActualAll(mrs.ts);
				//通知客户端
				sendUtils.sendFcsj(mrs.sch);
				//持久化
				dayOfSchedule.save(mrs.sch);
			}
			
			if(inRsList.size() > 0){
				//排序后的第一个 就是最合适的匹配
				Collections.sort(inRsList, new MatchResultComparator());
				mrs = inRsList.get(0);
				
				mrs.sch.setZdsjActualAll(mrs.ts);
				int doneSum = dayOfSchedule.doneSum(mrs.sch.getClZbh());
				ScheduleRealInfo next = dayOfSchedule.next(mrs.sch);
				if(null != next){
					next.setQdzArrDateSJ(mrs.sch.getZdsjActual());
					//下发调度指令
					//directiveService.send60Dispatch(next, doneSum, "系统");
				}
				else{
					//下发文本指令(已结束运营)
					directiveService.send60Phrase(nbbm, "到达终点 " + mrs.sch.getZdzName() + ",已完成当日所有排班。", "系统");
				}
				//通知客户端
				sendUtils.sendZdsj(mrs.sch, next, doneSum);
				//持久化
				dayOfSchedule.save(mrs.sch);
			}
		}
		
		public MatchResult match(ArrivalEntity arr, ScheduleRealInfo sch){
			MatchResult mrs = new MatchResult();
			mrs.inOut = arr.getInOut();
			mrs.sch = sch;
			mrs.ts = arr.getTs();
			
			if(arr.getInOut() == 1){
				if(sch.getFcsjActual() == null 
						&& sch.getQdzName().equals(arr.getStopName())
						&& dayOfSchedule.validStartTime(sch, arr.getTs())){
					
						mrs.diff = arr.getTs() - sch.getDfsjT();
						if(Math.abs(mrs.diff) < MAX_RANGE)
							mrs.success = true;
				}
			}
			else if(arr.getInOut() == 0 && sch.getZdsj() != null){
				if(sch.getZdsjActual() == null 
						&& sch.getZdzName().equals(arr.getStopName())
						&& dayOfSchedule.validEndTime(sch, arr.getTs())){
						
						mrs.diff = arr.getTs() - sch.getZdsjT();
						if(Math.abs(mrs.diff) < MAX_RANGE)
							mrs.success = true;
				}
			}
			
			return mrs;
		}
		
		/**
		 * 
		 * @Title: lastMatchPoint 
		 * @Description: TODO(最后一个已实发的班次索引) 
		 */
		public int lastMatchPoint(List<ScheduleRealInfo> schList){
			int len = schList.size()
						,rs = 0;
			
			ScheduleRealInfo sch;
			for(int i = len - 2; i >= 0; i --){
				sch = schList.get(i);
				if(sch.getFcsjActual() != null){
					rs = i;
					if(sch.getStatus() == 2)
						rs ++;
					break;
				}
			}
			return rs;
		}
		
		public long lastMatchTime(ScheduleRealInfo sch){
			Long t = 0L;
			if(null != sch.getFcsjActualTime())
				t = sch.getFcsjActualTime();
			if(null != sch.getZdsjActualTime())
				t = sch.getZdsjActualTime();
			return t;
		}
		
		/**
		 * 
		 * @Title: afterByTime 
		 * @Description: TODO(参数时间戳之后的起始索引) 
		 */
		public int afterByTime(List<ArrivalEntity> arrList, long t){
			int len = arrList.size()
				,rs = len - 1;
			
			for(int i = 0; i < len; i ++){
				if(arrList.get(i).getTs() > t){
					rs = i;
					break;
				}
			}
			return rs;
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		sendUtils = arg0.getBean(SendUtils.class);
		dayOfSchedule = arg0.getBean(DayOfSchedule.class);
		directiveService = arg0.getBean(DirectiveService.class);
	}
}