Commit b2f5225063661ee5e543fb44b8f20480948b1f0a

Authored by 徐烜
2 parents 731c8e43 85e1836c

Merge branch 'pudong' of http://222.66.0.204:8090//panzhaov5/bsth_control into pudong

Showing 61 changed files with 6750 additions and 6301 deletions
src/main/java/com/bsth/Application.java
... ... @@ -17,7 +17,7 @@ import java.util.concurrent.ScheduledExecutorService;
17 17 @SpringBootApplication
18 18 public class Application extends SpringBootServletInitializer {
19 19  
20   - public static ScheduledExecutorService mainServices = Executors.newScheduledThreadPool(17);
  20 + public static ScheduledExecutorService mainServices = Executors.newScheduledThreadPool(18);
21 21  
22 22 @Override
23 23 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
... ...
src/main/java/com/bsth/XDApplication.java
1 1 package com.bsth;
2 2  
3 3 import com.bsth.data.BasicData;
  4 +import com.bsth.data.LineVersionsData;
4 5 import com.bsth.data.ThreadMonotor;
5 6 import com.bsth.data.car_out_info.UpdateDBThread;
6 7 import com.bsth.data.directive.DirectivesPstThread;
7 8 import com.bsth.data.forecast.SampleTimeDataLoader;
8 9 import com.bsth.data.gpsdata_v2.thread.GpsDataLoaderThread;
  10 +import com.bsth.data.gpsdata_v2.thread.OfflineMonitorThread;
9 11 import com.bsth.data.msg_queue.DirectivePushQueue;
10 12 import com.bsth.data.msg_queue.WebSocketPushQueue;
11 13 import com.bsth.data.schedule.DayOfSchedule;
... ... @@ -67,6 +69,12 @@ public class XDApplication implements CommandLineRunner {
67 69 @Autowired
68 70 GpsDataLoaderThread gpsDataLoader;
69 71  
  72 + @Autowired
  73 + OfflineMonitorThread offlineMonitorThread;
  74 +
  75 + @Autowired
  76 + LineVersionsData lineVersionsData;
  77 +
70 78 private static long timeDiff;
71 79 private static long timeDiffTraffic;
72 80  
... ... @@ -134,11 +142,11 @@ public class XDApplication implements CommandLineRunner {
134 142 sexec.scheduleWithFixedDelay(scheduleLateThread, 70, 30, TimeUnit.SECONDS);//检查班次误点
135 143 sexec.scheduleWithFixedDelay(gpsDataLoader, 100, 2, TimeUnit.SECONDS);//抓取GPS数据
136 144  
137   - //sexec.scheduleWithFixedDelay(offlineMonitorThread, 120, 60, TimeUnit.SECONDS);//GPS设备掉离线
  145 + sexec.scheduleWithFixedDelay(offlineMonitorThread, 120, 60, TimeUnit.SECONDS);//GPS设备掉离线
138 146 sexec.scheduleWithFixedDelay(schedulePstThread, 120, 10, TimeUnit.SECONDS);//班次延迟入库线程
139 147 sexec.scheduleWithFixedDelay(seiPstThread, 160, 60, TimeUnit.SECONDS);//班次修正日志入库
140 148 sexec.scheduleWithFixedDelay(directivesPstThread, 180, 120, TimeUnit.SECONDS);//调度指令延迟入库
141   - sexec.scheduleWithFixedDelay(threadMonotor, 240, 60, TimeUnit.SECONDS);//线程监听(防止重要的线程阻塞、异常结束。以及部分主备切换工作)
  149 + //sexec.scheduleWithFixedDelay(threadMonotor, 240, 60, TimeUnit.SECONDS);//线程监听(防止重要的线程阻塞、异常结束。以及部分主备切换工作)
142 150 sexec.scheduleWithFixedDelay(sampleTimeDataLoader, 140, 120 * 60, TimeUnit.SECONDS);//到离站预测需要的站点间耗时数据
143 151 sexec.scheduleWithFixedDelay(basicDataLoader, 2, 2, TimeUnit.HOURS);//基础数据更新
144 152 sexec.scheduleWithFixedDelay(autoExecScanThread, 160, 50, TimeUnit.SECONDS);//班次自动执行
... ... @@ -156,5 +164,8 @@ public class XDApplication implements CommandLineRunner {
156 164 sexec.scheduleAtFixedRate(submitToTrafficManage, timeDiffTraffic / 1000, 60 * 60 * 24, TimeUnit.SECONDS);
157 165 //计算油、公里加注
158 166 sexec.scheduleAtFixedRate(calcOilThread, timeDiff / 1000, 60 * 60 * 24, TimeUnit.SECONDS);
  167 +
  168 + //线路版本更新
  169 + sexec.scheduleWithFixedDelay(lineVersionsData, 60 * 5, 60 * 15, TimeUnit.SECONDS);
159 170 }
160 171 }
... ...
src/main/java/com/bsth/controller/oil/DlbController.java
... ... @@ -163,6 +163,7 @@ public class DlbController extends BaseController<Dlb, Integer>{
163 163 m.put("hd", y.getHd()<=0?"0":y.getHd());
164 164 String shyy ="无";
165 165 if(y.getShyy()!=null){
  166 + shyy=y.getShyy();
166 167 if(shyy.equals("1")){shyy="票务用油";}
167 168 else if(shyy.equals("2")){shyy="保养用油";}
168 169 else if(shyy.equals("3")){shyy="报废车用油";}
... ...
src/main/java/com/bsth/data/gpsdata_v2/DataHandleProcess.java
... ... @@ -68,7 +68,7 @@ public class DataHandleProcess {
68 68 count = new CountDownLatch(ks.size());
69 69  
70 70 for (Integer index : ks) {
71   - threadPool.submit(new SignalHandleThread(dataListMap.get(index), count));
  71 + threadPool.execute(new SignalHandleThread(dataListMap.get(index), count));
72 72 }
73 73  
74 74 //等待子线程结束
... ... @@ -132,4 +132,4 @@ public class DataHandleProcess {
132 132 return t;
133 133 }
134 134 }
135 135 -}
  136 +}
136 137 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/GpsRealData.java
1   -package com.bsth.data.gpsdata_v2;
2   -
3   -import com.bsth.data.BasicData;
4   -import com.bsth.data.forecast.ForecastRealServer;
5   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
6   -import com.bsth.data.schedule.DayOfSchedule;
7   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
8   -import com.google.common.collect.TreeMultimap;
9   -import org.apache.commons.lang3.StringUtils;
10   -import org.slf4j.Logger;
11   -import org.slf4j.LoggerFactory;
12   -import org.springframework.beans.factory.annotation.Autowired;
13   -import org.springframework.stereotype.Component;
14   -
15   -import java.util.*;
16   -import java.util.concurrent.ConcurrentHashMap;
17   -import java.util.concurrent.ConcurrentMap;
18   -
19   -/**
20   - * @author PanZhao
21   - * @ClassName: GpsRealData
22   - * @Description: TODO(实时GPS数据集合)
23   - * @date 2016年8月12日 下午2:04:41
24   - */
25   -@Component
26   -public class GpsRealData {
27   -
28   - static Logger logger = LoggerFactory.getLogger(GpsRealData.class);
29   -
30   - private static ConcurrentMap<String, GpsEntity> gpsMap;
31   -
32   - //按线路分组设备号
33   - private static TreeMultimap<String, String> lineCode2Devices;
34   -
35   - @Autowired
36   - DayOfSchedule dayOfSchedule;
37   -
38   - @Autowired
39   - ForecastRealServer forecastRealServer;
40   -
41   - /**
42   - * 构造函数
43   - */
44   - public GpsRealData() {
45   - gpsMap = new ConcurrentHashMap<>();
46   - lineCode2Devices = TreeMultimap.create();
47   - }
48   -
49   -
50   - public void put(GpsEntity gps) {
51   - String device = gps.getDeviceId();
52   - GpsEntity old = gpsMap.get(device);
53   -
54   - try {
55   - if (!StringUtils.isEmpty(gps.getStopNo())) {
56   - //站点编码改变
57   - if (null == old || !gps.getStopNo().equals(old.getStopNo())) {
58   - gps.setArrTime(gps.getTimestamp());
59   - //预测到达终点时间
60   - forecastRealServer.forecast(gps.getNbbm(), gps);
61   - } else {
62   - gps.setArrTime(old.getArrTime());
63   - //不预测, 重新计算终点时间
64   - gps.setExpectStopTime(forecastRealServer.expectStopTime(gps.getNbbm()));
65   - }
66   - }
67   -
68   - //刷新对照
69   - gpsMap.put(device, gps);
70   - if (StringUtils.isNotBlank(gps.getLineId())) {
71   - //站点名称
72   - gps.setStationName(getStationName(gps));
73   - lineCode2Devices.put(gps.getLineId(), device);
74   -
75   - if(old != null && !gps.getLineId().equals(old.getLineId()))
76   - lineCode2Devices.remove(old.getLineId(), device);
77   - }
78   -
79   - //车辆换设备了
80   - String nbbm = gps.getNbbm();
81   - if(old != null && StringUtils.isNotEmpty(nbbm) && !nbbm.equals(old.getNbbm())){
82   - List<GpsEntity> list = findByNbbm(nbbm);
83   - for(GpsEntity g : list){
84   - if(!g.getDeviceId().equals(device))
85   - gpsMap.remove(g.getDeviceId());
86   - }
87   - }
88   - } catch (Exception e) {
89   - logger.error("", e);
90   - }
91   - }
92   -
93   - public String getStationName(GpsEntity gps) {
94   - return BasicData.getStationNameByCode(gps.getStopNo(), gps.getLineId() + "_" + gps.getUpDown() + "_");
95   - }
96   -
97   - /**
98   - * @Title: get @Description: TODO(设备号获取GPS)
99   - */
100   - public GpsEntity get(String deviceId) {
101   - return gpsMap.get(deviceId);
102   - }
103   -
104   - public List<GpsEntity> findByNbbm(String nbbm){
105   - Collection<GpsEntity> arr = gpsMap.values();
106   - List<GpsEntity> rs = new ArrayList<>();
107   - for(GpsEntity g : arr){
108   - if(nbbm.equals(g.getNbbm()))
109   - rs.add(g);
110   - }
111   - return rs;
112   - }
113   -
114   - public GpsEntity getByNbbm(String nbbm){
115   - String device = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
116   - if(StringUtils.isNotBlank(device))
117   - return get(device);
118   - else
119   - return null;
120   - }
121   -
122   - /**
123   - * @Title: get @Description: TODO(线路编码获取GPS集合) @throws
124   - */
125   - public List<GpsEntity> getByLine(String lineCode) {
126   - NavigableSet<String> set = lineCode2Devices.get(lineCode);
127   -
128   - List<GpsEntity> rs = new ArrayList<>();
129   - GpsEntity gps;
130   - ScheduleRealInfo sch;
131   - for (String device : set) {
132   - gps = gpsMap.get(device);
133   - //过滤异常GPS数据
134   - if (gps == null || StringUtils.isBlank(gps.getNbbm()))
135   - continue;
136   -
137   - sch = dayOfSchedule.execPlanMap().get(gps.getNbbm());
138   - if (null != sch)
139   - gps.setSchId(sch.getId());
140   - rs.add(gps);
141   - }
142   -
143   - return rs;
144   - }
145   -
146   - public List<GpsEntity> get(List<String> pArray) {
147   - List<GpsEntity> list = new ArrayList<>();
148   -
149   - for (String code : pArray)
150   - list.addAll(getByLine(code));
151   - return list;
152   - }
153   -
154   - public Set<String> allDevices() {
155   - return gpsMap.keySet();
156   - }
157   -
158   - public Collection<GpsEntity> all() {
159   - return gpsMap.values();
160   - }
161   -
162   - public void remove(String device) {
163   - gpsMap.remove(device);
164   - }
  1 +package com.bsth.data.gpsdata_v2;
  2 +
  3 +import com.bsth.data.BasicData;
  4 +import com.bsth.data.forecast.ForecastRealServer;
  5 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  6 +import com.bsth.data.schedule.DayOfSchedule;
  7 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  8 +import com.google.common.collect.TreeMultimap;
  9 +import org.apache.commons.lang3.StringUtils;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.stereotype.Component;
  14 +
  15 +import java.util.*;
  16 +import java.util.concurrent.ConcurrentHashMap;
  17 +import java.util.concurrent.ConcurrentMap;
  18 +
  19 +/**
  20 + * @author PanZhao
  21 + * @ClassName: GpsRealData
  22 + * @Description: TODO(实时GPS数据集合)
  23 + * @date 2016年8月12日 下午2:04:41
  24 + */
  25 +@Component
  26 +public class GpsRealData {
  27 +
  28 + static Logger logger = LoggerFactory.getLogger(GpsRealData.class);
  29 +
  30 + private static ConcurrentMap<String, GpsEntity> gpsMap;
  31 +
  32 + //按线路分组设备号
  33 + private static TreeMultimap<String, String> lineCode2Devices;
  34 +
  35 + @Autowired
  36 + DayOfSchedule dayOfSchedule;
  37 +
  38 + @Autowired
  39 + ForecastRealServer forecastRealServer;
  40 +
  41 + /**
  42 + * 构造函数
  43 + */
  44 + public GpsRealData() {
  45 + gpsMap = new ConcurrentHashMap<>();
  46 + lineCode2Devices = TreeMultimap.create();
  47 + }
  48 +
  49 +
  50 + public void put(GpsEntity gps) {
  51 + String device = gps.getDeviceId();
  52 + GpsEntity old = gpsMap.get(device);
  53 +
  54 + try {
  55 + if (!StringUtils.isEmpty(gps.getStopNo())) {
  56 + //站点编码改变
  57 + if (null == old || !gps.getStopNo().equals(old.getStopNo())) {
  58 + gps.setArrTime(gps.getTimestamp());
  59 + //预测到达终点时间
  60 + forecastRealServer.forecast(gps.getNbbm(), gps);
  61 + } else {
  62 + gps.setArrTime(old.getArrTime());
  63 + //不预测, 重新计算终点时间
  64 + gps.setExpectStopTime(forecastRealServer.expectStopTime(gps.getNbbm()));
  65 + }
  66 + }
  67 +
  68 + //刷新对照
  69 + gpsMap.put(device, gps);
  70 + if (StringUtils.isNotBlank(gps.getLineId())) {
  71 + //站点名称
  72 + gps.setStationName(getStationName(gps));
  73 + lineCode2Devices.put(gps.getLineId(), device);
  74 +
  75 + if(old != null && !gps.getLineId().equals(old.getLineId()))
  76 + lineCode2Devices.remove(old.getLineId(), device);
  77 + }
  78 +
  79 + //车辆换设备了
  80 + String nbbm = gps.getNbbm();
  81 + if(old != null && StringUtils.isNotEmpty(nbbm) && !nbbm.equals(old.getNbbm())){
  82 + List<GpsEntity> list = findByNbbm(nbbm);
  83 + for(GpsEntity g : list){
  84 + if(!g.getDeviceId().equals(device))
  85 + gpsMap.remove(g.getDeviceId());
  86 + }
  87 + }
  88 + } catch (Exception e) {
  89 + logger.error("", e);
  90 + }
  91 + }
  92 +
  93 + public String getStationName(GpsEntity gps) {
  94 + return BasicData.getStationNameByCode(gps.getStopNo(), gps.getLineId() + "_" + gps.getUpDown() + "_");
  95 + }
  96 +
  97 + /**
  98 + * @Title: get @Description: TODO(设备号获取GPS)
  99 + */
  100 + public GpsEntity get(String deviceId) {
  101 + return gpsMap.get(deviceId);
  102 + }
  103 +
  104 + public List<GpsEntity> findByNbbm(String nbbm){
  105 + Collection<GpsEntity> arr = gpsMap.values();
  106 + List<GpsEntity> rs = new ArrayList<>();
  107 + for(GpsEntity g : arr){
  108 + if(nbbm.equals(g.getNbbm()))
  109 + rs.add(g);
  110 + }
  111 + return rs;
  112 + }
  113 +
  114 + public GpsEntity getByNbbm(String nbbm){
  115 + String device = BasicData.deviceId2NbbmMap.inverse().get(nbbm);
  116 + if(StringUtils.isNotBlank(device))
  117 + return get(device);
  118 + else
  119 + return null;
  120 + }
  121 +
  122 + /**
  123 + * @Title: get @Description: TODO(线路编码获取GPS集合) @throws
  124 + */
  125 + public List<GpsEntity> getByLine(String lineCode) {
  126 + NavigableSet<String> set = lineCode2Devices.get(lineCode);
  127 +
  128 + List<GpsEntity> rs = new ArrayList<>();
  129 + GpsEntity gps;
  130 + ScheduleRealInfo sch;
  131 + for (String device : set) {
  132 + gps = gpsMap.get(device);
  133 + //过滤异常GPS数据
  134 + if (gps == null || StringUtils.isBlank(gps.getNbbm()))
  135 + continue;
  136 +
  137 + sch = dayOfSchedule.execPlanMap().get(gps.getNbbm());
  138 + if (null != sch)
  139 + gps.setSchId(sch.getId());
  140 + rs.add(gps);
  141 + }
  142 +
  143 + return rs;
  144 + }
  145 +
  146 + public List<GpsEntity> get(List<String> pArray) {
  147 + List<GpsEntity> list = new ArrayList<>();
  148 +
  149 + for (String code : pArray)
  150 + list.addAll(getByLine(code));
  151 + return list;
  152 + }
  153 +
  154 + public Set<String> allDevices() {
  155 + return gpsMap.keySet();
  156 + }
  157 +
  158 + public Collection<GpsEntity> all() {
  159 + return gpsMap.values();
  160 + }
  161 +
  162 + public void remove(String device) {
  163 + gpsMap.remove(device);
  164 + }
165 165 }
166 166 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/cache/GeoCacheData.java
... ... @@ -278,7 +278,7 @@ public class GeoCacheData {
278 278 int len = coords.length;
279 279 for (int i = 0; i < len; i++) {
280 280 temps = coords[i].split(" ");
281   - cds.add(new Point(Float.parseFloat(temps[1]), Float.parseFloat(temps[0])));
  281 + cds.add(new Point(Float.parseFloat(temps[0]), Float.parseFloat(temps[1])));
282 282 }
283 283 return new Polygon(cds);
284 284 }
... ... @@ -308,4 +308,4 @@ public class GeoCacheData {
308 308 public static Map<String, String> sectionCode2NameMap(){
309 309 return sectionCode2Name;
310 310 }
311 311 -}
  312 +}
312 313 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/cache/GpsCacheData.java
1   -package com.bsth.data.gpsdata_v2.cache;
2   -
3   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
4   -import com.bsth.data.gpsdata_v2.entity.StationRoute;
5   -import com.bsth.data.gpsdata_v2.entity.trail.GpsExecTrail;
6   -import com.bsth.data.gpsdata_v2.utils.CircleQueue;
7   -import com.google.common.collect.ArrayListMultimap;
8   -import org.slf4j.Logger;
9   -import org.slf4j.LoggerFactory;
10   -
11   -import java.util.*;
12   -
13   -/**
14   - * gps 数据缓存
15   - * Created by panzhao on 2017/11/15.
16   - */
17   -public class GpsCacheData {
18   -
19   - /**
20   - * 每辆车缓存最后300条gps
21   - */
22   - private static final int CACHE_SIZE = 300;
23   - private static Map<String, CircleQueue<GpsEntity>> gpsCacheMap = new HashMap<>();
24   -
25   - /**
26   - * 车辆执行班次的详细 进出站数据
27   - */
28   - private static ArrayListMultimap<String, GpsExecTrail> trailListMultimap = ArrayListMultimap.create();
29   -
30   - static Logger logger = LoggerFactory.getLogger(GpsCacheData.class);
31   -
32   - public static CircleQueue<GpsEntity> getGps(String device) {
33   - return gpsCacheMap.get(device);
34   - }
35   -
36   - public static GpsExecTrail gpsExecTrail(String nbbm){
37   - List<GpsExecTrail> list = trailListMultimap.get(nbbm);
38   -
39   - GpsExecTrail trail;
40   - if(null == list || list.size() == 0
41   - || list.get(list.size() - 1).isEnd()){
42   - trail = new GpsExecTrail();
43   -
44   - trailListMultimap.put(nbbm, trail);
45   - }
46   - else{
47   - trail = list.get(list.size() - 1);
48   - }
49   -
50   - return trail;
51   - }
52   -
53   - public static void out(GpsEntity gps){
54   - GpsExecTrail trail = gpsExecTrail(gps.getNbbm());
55   - trail.getSrs().add(gps);
56   -
57   - }
58   -
59   - public static void in(GpsEntity gps, boolean end){
60   - GpsExecTrail trail = gpsExecTrail(gps.getNbbm());
61   - trail.getSrs().add(gps);
62   - trail.setEnd(end);
63   - }
64   -
65   - public static GpsEntity getPrev(GpsEntity gps){
66   - CircleQueue<GpsEntity> queue = gpsCacheMap.get(gps.getDeviceId());
67   - if(queue != null)
68   - return queue.getTail();
69   - return null;
70   - }
71   -
72   - public static void putGps(GpsEntity gps) {
73   - CircleQueue<GpsEntity> queue = gpsCacheMap.get(gps.getDeviceId());
74   - if (queue == null) {
75   - queue = new CircleQueue<>(CACHE_SIZE);
76   - gpsCacheMap.put(gps.getDeviceId(), queue);
77   - }
78   - queue.add(gps);
79   - }
80   -
81   - public static void clear(String deviceId) {
82   - try {
83   - CircleQueue<GpsEntity> queue = gpsCacheMap.get(deviceId);
84   - if (queue != null)
85   - queue.clear();
86   - } catch (Exception e) {
87   - logger.error("", e);
88   - }
89   - }
90   -
91   - public static StationRoute prevStation(GpsEntity gps) {
92   - List<GpsExecTrail> trails = trailListMultimap.get(gps.getNbbm());
93   - if(null == trails || trails.size() == 0)
94   - return null;
95   -
96   - GpsEntity prev;
97   - for(int i = trails.size() - 1; i > 0; i--){
98   - prev = trails.get(i).getSrs().peekLast();
99   -
100   - if(prev != null){
101   - return GeoCacheData.getRouteCode(prev);
102   - }
103   - }
104   - return null;
105   - }
106   -
107   - public static List<StationRoute> prevMultiStation(GpsEntity gps) {
108   - List<StationRoute> rs = new ArrayList<>();
109   - List<GpsExecTrail> trails = trailListMultimap.get(gps.getNbbm());
110   - if(null == trails || trails.size() == 0)
111   - return null;
112   -
113   - for(int i = trails.size() - 1; i > 0; i--){
114   - rs.addAll(searchLinked(trails.get(i).getSrs(), gps.getUpDown()));
115   - if(rs.size() > 3)
116   - break;
117   - }
118   - return rs;
119   - }
120   -
121   - private static List<StationRoute> searchLinked(LinkedList<GpsEntity> list, int upDown){
122   - List<StationRoute> rs = new ArrayList<>();
123   - Iterator<GpsEntity> iterator = list.iterator();
124   - GpsEntity gps;
125   - int prevCode=0;
126   - while (iterator.hasNext()){
127   - gps = iterator.next();
128   - if(gps.getInstation()!=1)
129   - continue;
130   -
131   - if(gps.getUpDown() != upDown)
132   - break;
133   -
134   - if(gps.getStation().getRouteSort() != prevCode)
135   - rs.add(gps.getStation());
136   -
137   - prevCode = gps.getStation().getRouteSort();
138   -
139   - if(rs.size() >= 3)
140   - break;
141   - }
142   - return rs;
143   - }
144   -}
  1 +package com.bsth.data.gpsdata_v2.cache;
  2 +
  3 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  4 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  5 +import com.bsth.data.gpsdata_v2.entity.trail.GpsExecTrail;
  6 +import com.bsth.data.gpsdata_v2.utils.CircleQueue;
  7 +import com.google.common.collect.ArrayListMultimap;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +
  11 +import java.util.*;
  12 +
  13 +/**
  14 + * gps 数据缓存
  15 + * Created by panzhao on 2017/11/15.
  16 + */
  17 +public class GpsCacheData {
  18 +
  19 + /**
  20 + * 每辆车缓存最后300条gps
  21 + */
  22 + private static final int CACHE_SIZE = 300;
  23 + private static Map<String, CircleQueue<GpsEntity>> gpsCacheMap = new HashMap<>();
  24 +
  25 + /**
  26 + * 车辆执行班次的详细 进出站数据
  27 + */
  28 + private static ArrayListMultimap<String, GpsExecTrail> trailListMultimap = ArrayListMultimap.create();
  29 +
  30 + static Logger logger = LoggerFactory.getLogger(GpsCacheData.class);
  31 +
  32 + public static CircleQueue<GpsEntity> getGps(String device) {
  33 + return gpsCacheMap.get(device);
  34 + }
  35 +
  36 + public static GpsExecTrail gpsExecTrail(String nbbm){
  37 + List<GpsExecTrail> list = trailListMultimap.get(nbbm);
  38 +
  39 + GpsExecTrail trail;
  40 + if(null == list || list.size() == 0
  41 + || list.get(list.size() - 1).isEnd()){
  42 + trail = new GpsExecTrail();
  43 +
  44 + trailListMultimap.put(nbbm, trail);
  45 + }
  46 + else{
  47 + trail = list.get(list.size() - 1);
  48 + }
  49 +
  50 + return trail;
  51 + }
  52 +
  53 + public static void out(GpsEntity gps){
  54 + GpsExecTrail trail = gpsExecTrail(gps.getNbbm());
  55 + trail.getSrs().add(gps);
  56 +
  57 + }
  58 +
  59 + public static void in(GpsEntity gps, boolean end){
  60 + GpsExecTrail trail = gpsExecTrail(gps.getNbbm());
  61 + trail.getSrs().add(gps);
  62 + trail.setEnd(end);
  63 + }
  64 +
  65 + public static GpsEntity getPrev(GpsEntity gps){
  66 + CircleQueue<GpsEntity> queue = gpsCacheMap.get(gps.getDeviceId());
  67 + if(queue != null)
  68 + return queue.getTail();
  69 + return null;
  70 + }
  71 +
  72 + public static void putGps(GpsEntity gps) {
  73 + CircleQueue<GpsEntity> queue = gpsCacheMap.get(gps.getDeviceId());
  74 + if (queue == null) {
  75 + queue = new CircleQueue<>(CACHE_SIZE);
  76 + gpsCacheMap.put(gps.getDeviceId(), queue);
  77 + }
  78 + queue.add(gps);
  79 + }
  80 +
  81 + public static void clear(String deviceId) {
  82 + try {
  83 + CircleQueue<GpsEntity> queue = gpsCacheMap.get(deviceId);
  84 + if (queue != null)
  85 + queue.clear();
  86 + } catch (Exception e) {
  87 + logger.error("", e);
  88 + }
  89 + }
  90 +
  91 + public static StationRoute prevStation(GpsEntity gps) {
  92 + List<GpsExecTrail> trails = trailListMultimap.get(gps.getNbbm());
  93 + if(null == trails || trails.size() == 0)
  94 + return null;
  95 +
  96 + GpsEntity prev;
  97 + for(int i = trails.size() - 1; i > 0; i--){
  98 + prev = trails.get(i).getSrs().peekLast();
  99 +
  100 + if(prev != null){
  101 + return GeoCacheData.getRouteCode(prev);
  102 + }
  103 + }
  104 + return null;
  105 + }
  106 +
  107 + public static List<StationRoute> prevMultiStation(GpsEntity gps) {
  108 + List<StationRoute> rs = new ArrayList<>();
  109 + List<GpsExecTrail> trails = trailListMultimap.get(gps.getNbbm());
  110 + if(null == trails || trails.size() == 0)
  111 + return null;
  112 +
  113 + for(int i = trails.size() - 1; i > 0; i--){
  114 + rs.addAll(searchLinked(trails.get(i).getSrs(), gps.getUpDown()));
  115 + if(rs.size() > 3)
  116 + break;
  117 + }
  118 + return rs;
  119 + }
  120 +
  121 + private static List<StationRoute> searchLinked(LinkedList<GpsEntity> list, int upDown){
  122 + List<StationRoute> rs = new ArrayList<>();
  123 + Iterator<GpsEntity> iterator = list.iterator();
  124 + GpsEntity gps;
  125 + int prevCode=0;
  126 + while (iterator.hasNext()){
  127 + gps = iterator.next();
  128 + if(gps.getInstation()!=1)
  129 + continue;
  130 +
  131 + if(gps.getUpDown() != upDown)
  132 + break;
  133 +
  134 + if(gps.getStation().getRouteSort() != prevCode)
  135 + rs.add(gps.getStation());
  136 +
  137 + prevCode = gps.getStation().getRouteSort();
  138 +
  139 + if(rs.size() >= 3)
  140 + break;
  141 + }
  142 + return rs;
  143 + }
  144 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/CtLineString.java
1   -package com.bsth.data.gpsdata_v2.entity;
2   -
3   -import com.bsth.util.Geo.Point;
4   -
5   -import java.util.List;
6   -
7   -/**
8   - * Created by panzhao on 2017/11/15.
9   - */
10   -public class CtLineString {
11   -
12   - public CtLineString(){}
13   - public CtLineString(List<Point> ps){
14   - s = ps.get(0);
15   - e = ps.get(1);
16   - }
17   -
18   - Point s;
19   -
20   - Point e;
21   -
22   - public Point getS() {
23   - return s;
24   - }
25   -
26   - public void setS(Point s) {
27   - this.s = s;
28   - }
29   -
30   - public Point getE() {
31   - return e;
32   - }
33   -
34   - public void setE(Point e) {
35   - this.e = e;
36   - }
37   -}
  1 +package com.bsth.data.gpsdata_v2.entity;
  2 +
  3 +import com.bsth.util.Geo.Point;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * Created by panzhao on 2017/11/15.
  9 + */
  10 +public class CtLineString {
  11 +
  12 + public CtLineString(){}
  13 + public CtLineString(List<Point> ps){
  14 + s = ps.get(0);
  15 + e = ps.get(1);
  16 + }
  17 +
  18 + Point s;
  19 +
  20 + Point e;
  21 +
  22 + public Point getS() {
  23 + return s;
  24 + }
  25 +
  26 + public void setS(Point s) {
  27 + this.s = s;
  28 + }
  29 +
  30 + public Point getE() {
  31 + return e;
  32 + }
  33 +
  34 + public void setE(Point e) {
  35 + this.e = e;
  36 + }
  37 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/GpsEntity.java
1   -package com.bsth.data.gpsdata_v2.entity;
2   -
3   -import com.fasterxml.jackson.annotation.JsonIgnore;
4   -
5   -/**
6   - *
7   - * @ClassName: GpsRealData
8   - * @Description: TODO(HTTP接口的实时GPS数据)
9   - * @author PanZhao
10   - * @date 2016年5月11日 下午4:32:07
11   - *
12   - */
13   -public class GpsEntity implements Cloneable{
14   -
15   - /** 公司代码 */
16   - private Short companyCode;
17   -
18   - /** 线路编码 */
19   - private String lineId;
20   -
21   - /** 设备编码 */
22   - private String deviceId;
23   -
24   - /** 停车场编码 */
25   - private String carparkNo;
26   -
27   - /** 站点编码 */
28   - private String stopNo;
29   -
30   - /** 站点名称 */
31   - private String stationName;
32   -
33   - /** 到站时间 */
34   - private long arrTime;
35   -
36   - /** 经度 */
37   - private Float lon;
38   -
39   - /** 纬度 */
40   - private Float lat;
41   -
42   - /** GPS发送时间戳 */
43   - private Long timestamp;
44   -
45   - /** 网关收到时间 */
46   - private Long serverTimestamp;
47   -
48   - /** 速度 */
49   - private Float speed;
50   -
51   - /** 方向(角度) */
52   - private float direction;
53   -
54   - /** 营运状态( 0 营运 ,1 非营运, -1 无效) */
55   - private Integer state;
56   -
57   - /** 上下行(0 上行 , 1 下行 , -1 无效) */
58   - private Byte upDown;
59   -
60   - /** 车辆内部编码 */
61   - private String nbbm;
62   -
63   - /** 预计到达终点时间 */
64   - private Float expectStopTime;
65   -
66   - /** 当前执行班次ID */
67   - private Long schId;
68   -
69   - private int version;
70   -
71   - /** 0: 站外 1:站内 2:场内 */
72   - private int instation;
73   -
74   - /** 站点信息,站内时有值 */
75   - @JsonIgnore
76   - private StationRoute station;
77   -
78   - /**
79   - * 前置约束 -站点编码
80   - */
81   - @JsonIgnore
82   - private String premiseCode;
83   -
84   - /** 状态 */
85   - private String signalState = "normal";
86   -
87   - /** 异常状态 */
88   - private String abnormalStatus;
89   -
90   - /** 越界距离 */
91   - private double outOfBoundDistance;
92   -
93   - /** gps是否有效 设备端发送的状态 */
94   - private int valid;
95   -
96   - /**
97   - * 数据来源
98   - * 1:网关
99   - * 0:转发
100   - */
101   - private int source = -1;
102   -
103   - public Object clone() {
104   - try {
105   - return super.clone();
106   - } catch (CloneNotSupportedException e) {
107   - return null;
108   - }
109   - }
110   -
111   - public String getDeviceId() {
112   - return deviceId;
113   - }
114   -
115   - public void setDeviceId(String deviceId) {
116   - this.deviceId = deviceId;
117   - }
118   -
119   - public String getCarparkNo() {
120   - return carparkNo;
121   - }
122   -
123   - public void setCarparkNo(String carparkNo) {
124   - this.carparkNo = carparkNo;
125   - }
126   -
127   - public String getStopNo() {
128   - return stopNo;
129   - }
130   -
131   - public void setStopNo(String stopNo) {
132   - this.stopNo = stopNo;
133   - }
134   -
135   - public Float getLon() {
136   - return lon;
137   - }
138   -
139   - public void setLon(Float lon) {
140   - this.lon = lon;
141   - }
142   -
143   - public Float getLat() {
144   - return lat;
145   - }
146   -
147   - public void setLat(Float lat) {
148   - this.lat = lat;
149   - }
150   -
151   - public Long getTimestamp() {
152   - return timestamp;
153   - }
154   -
155   - public void setTimestamp(Long timestamp) {
156   - this.timestamp = timestamp;
157   - }
158   -
159   -
160   - public Integer getState() {
161   - return state;
162   - }
163   -
164   - public void setState(Integer state) {
165   - this.state = state;
166   - }
167   -
168   - public String getNbbm() {
169   - return nbbm;
170   - }
171   -
172   - public void setNbbm(String nbbm) {
173   - this.nbbm = nbbm;
174   - }
175   -
176   - public String getStationName() {
177   - return stationName;
178   - }
179   -
180   - public void setStationName(String stationName) {
181   - this.stationName = stationName;
182   - }
183   -
184   - public long getArrTime() {
185   - return arrTime;
186   - }
187   -
188   - public void setArrTime(long arrTime) {
189   - this.arrTime = arrTime;
190   - }
191   -
192   - public Float getExpectStopTime() {
193   - return expectStopTime;
194   - }
195   -
196   - public void setExpectStopTime(Float expectStopTime) {
197   - this.expectStopTime = expectStopTime;
198   - }
199   -
200   - public String getLineId() {
201   - return lineId;
202   - }
203   -
204   - public void setLineId(String lineId) {
205   - this.lineId = lineId;
206   - }
207   -
208   - public Long getSchId() {
209   - return schId;
210   - }
211   -
212   - public void setSchId(Long schId) {
213   - this.schId = schId;
214   - }
215   -
216   -
217   - public int getVersion() {
218   - return version;
219   - }
220   -
221   - public void setVersion(int version) {
222   - this.version = version;
223   - }
224   -
225   - public StationRoute getStation() {
226   - return station;
227   - }
228   -
229   - public void setStation(StationRoute station) {
230   - this.station = station;
231   - }
232   -
233   - public String getSignalState() {
234   - return signalState;
235   - }
236   -
237   - public void setSignalState(String signalState) {
238   - this.signalState = signalState;
239   - }
240   -
241   - public int getInstation() {
242   - return instation;
243   - }
244   -
245   - public void setInstation(int instation) {
246   - this.instation = instation;
247   - }
248   -
249   - public String getAbnormalStatus() {
250   - return abnormalStatus;
251   - }
252   -
253   - public void setAbnormalStatus(String abnormalStatus) {
254   - this.abnormalStatus = abnormalStatus;
255   - }
256   -
257   - public double getOutOfBoundDistance() {
258   - return outOfBoundDistance;
259   - }
260   -
261   - public void setOutOfBoundDistance(double outOfBoundDistance) {
262   - this.outOfBoundDistance = outOfBoundDistance;
263   - }
264   -
265   - public int getValid() {
266   - return valid;
267   - }
268   -
269   - public void setValid(int valid) {
270   - this.valid = valid;
271   - }
272   -
273   -
274   -
275   - public short getCompanyCode() {
276   - return companyCode;
277   - }
278   -
279   - public void setCompanyCode(short companyCode) {
280   - this.companyCode = companyCode;
281   - }
282   -
283   - public Byte getUpDown() {
284   - return upDown;
285   - }
286   -
287   - public void setUpDown(Byte upDown) {
288   - this.upDown = upDown;
289   - }
290   -
291   -
292   - public float getDirection() {
293   - return direction;
294   - }
295   -
296   - public void setDirection(float direction) {
297   - this.direction = direction;
298   - }
299   -
300   - public Float getSpeed() {
301   - return speed;
302   - }
303   -
304   - public void setSpeed(Float speed) {
305   - this.speed = speed;
306   - }
307   -
308   - public int getSource() {
309   - return source;
310   - }
311   -
312   - public void setSource(int source) {
313   - this.source = source;
314   - }
315   -
316   - public void offline(){
317   - this.setAbnormalStatus("offline");
318   - }
319   -
320   -/* public boolean isOnline(){
321   - if(isOffline())
322   - return false;
323   -
324   - long t = System.currentTimeMillis();
325   -
326   - if((t - this.getServerTimestamp()) > 1000 * 60 * 2){
327   - return false;
328   - }
329   -
330   - if((this.getServerTimestamp() - t) > 1000 * 60 * 3){
331   - return false;
332   - }
333   - return true;
334   - }*/
335   -
336   - /**
337   - * 是否营运
338   - * @return
339   - */
340   - public boolean isService(){
341   - return state!=null && state==0;
342   - }
343   -
344   - public boolean isOffline(){
345   - return this.getAbnormalStatus() != null && this.getAbnormalStatus().equals("offline");
346   - }
347   -
348   - public Long getServerTimestamp() {
349   - return serverTimestamp;
350   - }
351   -
352   - public void setServerTimestamp(Long serverTimestamp) {
353   - this.serverTimestamp = serverTimestamp;
354   - }
355   -
356   - public String getPremiseCode() {
357   - return premiseCode;
358   - }
359   -
360   - public void setPremiseCode(String premiseCode) {
361   - this.premiseCode = premiseCode;
362   - }
363   -}
  1 +package com.bsth.data.gpsdata_v2.entity;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
  4 +
  5 +/**
  6 + *
  7 + * @ClassName: GpsRealData
  8 + * @Description: TODO(HTTP接口的实时GPS数据)
  9 + * @author PanZhao
  10 + * @date 2016年5月11日 下午4:32:07
  11 + *
  12 + */
  13 +public class GpsEntity implements Cloneable{
  14 +
  15 + /** 公司代码 */
  16 + private Short companyCode;
  17 +
  18 + /** 线路编码 */
  19 + private String lineId;
  20 +
  21 + /** 设备编码 */
  22 + private String deviceId;
  23 +
  24 + /** 停车场编码 */
  25 + private String carparkNo;
  26 +
  27 + /** 站点编码 */
  28 + private String stopNo;
  29 +
  30 + /** 站点名称 */
  31 + private String stationName;
  32 +
  33 + /** 到站时间 */
  34 + private long arrTime;
  35 +
  36 + /** 经度 */
  37 + private Float lon;
  38 +
  39 + /** 纬度 */
  40 + private Float lat;
  41 +
  42 + /** GPS发送时间戳 */
  43 + private Long timestamp;
  44 +
  45 + /** 网关收到时间 */
  46 + private Long serverTimestamp;
  47 +
  48 + /** 速度 */
  49 + private Float speed;
  50 +
  51 + /** 方向(角度) */
  52 + private float direction;
  53 +
  54 + /** 营运状态( 0 营运 ,1 非营运, -1 无效) */
  55 + private Integer state;
  56 +
  57 + /** 上下行(0 上行 , 1 下行 , -1 无效) */
  58 + private Byte upDown;
  59 +
  60 + /** 车辆内部编码 */
  61 + private String nbbm;
  62 +
  63 + /** 预计到达终点时间 */
  64 + private Float expectStopTime;
  65 +
  66 + /** 当前执行班次ID */
  67 + private Long schId;
  68 +
  69 + private int version;
  70 +
  71 + /** 0: 站外 1:站内 2:场内 */
  72 + private int instation;
  73 +
  74 + /** 站点信息,站内时有值 */
  75 + @JsonIgnore
  76 + private StationRoute station;
  77 +
  78 + /**
  79 + * 前置约束 -站点编码
  80 + */
  81 + @JsonIgnore
  82 + private String premiseCode;
  83 +
  84 + /** 状态 */
  85 + private String signalState = "normal";
  86 +
  87 + /** 异常状态 */
  88 + private String abnormalStatus;
  89 +
  90 + /** 越界距离 */
  91 + private double outOfBoundDistance;
  92 +
  93 + /** gps是否有效 设备端发送的状态 */
  94 + private int valid;
  95 +
  96 + /**
  97 + * 数据来源
  98 + * 1:网关
  99 + * 0:转发
  100 + */
  101 + private int source = -1;
  102 +
  103 + public Object clone() {
  104 + try {
  105 + return super.clone();
  106 + } catch (CloneNotSupportedException e) {
  107 + return null;
  108 + }
  109 + }
  110 +
  111 + public String getDeviceId() {
  112 + return deviceId;
  113 + }
  114 +
  115 + public void setDeviceId(String deviceId) {
  116 + this.deviceId = deviceId;
  117 + }
  118 +
  119 + public String getCarparkNo() {
  120 + return carparkNo;
  121 + }
  122 +
  123 + public void setCarparkNo(String carparkNo) {
  124 + this.carparkNo = carparkNo;
  125 + }
  126 +
  127 + public String getStopNo() {
  128 + return stopNo;
  129 + }
  130 +
  131 + public void setStopNo(String stopNo) {
  132 + this.stopNo = stopNo;
  133 + }
  134 +
  135 + public Float getLon() {
  136 + return lon;
  137 + }
  138 +
  139 + public void setLon(Float lon) {
  140 + this.lon = lon;
  141 + }
  142 +
  143 + public Float getLat() {
  144 + return lat;
  145 + }
  146 +
  147 + public void setLat(Float lat) {
  148 + this.lat = lat;
  149 + }
  150 +
  151 + public Long getTimestamp() {
  152 + return timestamp;
  153 + }
  154 +
  155 + public void setTimestamp(Long timestamp) {
  156 + this.timestamp = timestamp;
  157 + }
  158 +
  159 +
  160 + public Integer getState() {
  161 + return state;
  162 + }
  163 +
  164 + public void setState(Integer state) {
  165 + this.state = state;
  166 + }
  167 +
  168 + public String getNbbm() {
  169 + return nbbm;
  170 + }
  171 +
  172 + public void setNbbm(String nbbm) {
  173 + this.nbbm = nbbm;
  174 + }
  175 +
  176 + public String getStationName() {
  177 + return stationName;
  178 + }
  179 +
  180 + public void setStationName(String stationName) {
  181 + this.stationName = stationName;
  182 + }
  183 +
  184 + public long getArrTime() {
  185 + return arrTime;
  186 + }
  187 +
  188 + public void setArrTime(long arrTime) {
  189 + this.arrTime = arrTime;
  190 + }
  191 +
  192 + public Float getExpectStopTime() {
  193 + return expectStopTime;
  194 + }
  195 +
  196 + public void setExpectStopTime(Float expectStopTime) {
  197 + this.expectStopTime = expectStopTime;
  198 + }
  199 +
  200 + public String getLineId() {
  201 + return lineId;
  202 + }
  203 +
  204 + public void setLineId(String lineId) {
  205 + this.lineId = lineId;
  206 + }
  207 +
  208 + public Long getSchId() {
  209 + return schId;
  210 + }
  211 +
  212 + public void setSchId(Long schId) {
  213 + this.schId = schId;
  214 + }
  215 +
  216 +
  217 + public int getVersion() {
  218 + return version;
  219 + }
  220 +
  221 + public void setVersion(int version) {
  222 + this.version = version;
  223 + }
  224 +
  225 + public StationRoute getStation() {
  226 + return station;
  227 + }
  228 +
  229 + public void setStation(StationRoute station) {
  230 + this.station = station;
  231 + }
  232 +
  233 + public String getSignalState() {
  234 + return signalState;
  235 + }
  236 +
  237 + public void setSignalState(String signalState) {
  238 + this.signalState = signalState;
  239 + }
  240 +
  241 + public int getInstation() {
  242 + return instation;
  243 + }
  244 +
  245 + public void setInstation(int instation) {
  246 + this.instation = instation;
  247 + }
  248 +
  249 + public String getAbnormalStatus() {
  250 + return abnormalStatus;
  251 + }
  252 +
  253 + public void setAbnormalStatus(String abnormalStatus) {
  254 + this.abnormalStatus = abnormalStatus;
  255 + }
  256 +
  257 + public double getOutOfBoundDistance() {
  258 + return outOfBoundDistance;
  259 + }
  260 +
  261 + public void setOutOfBoundDistance(double outOfBoundDistance) {
  262 + this.outOfBoundDistance = outOfBoundDistance;
  263 + }
  264 +
  265 + public int getValid() {
  266 + return valid;
  267 + }
  268 +
  269 + public void setValid(int valid) {
  270 + this.valid = valid;
  271 + }
  272 +
  273 +
  274 +
  275 + public short getCompanyCode() {
  276 + return companyCode;
  277 + }
  278 +
  279 + public void setCompanyCode(short companyCode) {
  280 + this.companyCode = companyCode;
  281 + }
  282 +
  283 + public Byte getUpDown() {
  284 + return upDown;
  285 + }
  286 +
  287 + public void setUpDown(Byte upDown) {
  288 + this.upDown = upDown;
  289 + }
  290 +
  291 +
  292 + public float getDirection() {
  293 + return direction;
  294 + }
  295 +
  296 + public void setDirection(float direction) {
  297 + this.direction = direction;
  298 + }
  299 +
  300 + public Float getSpeed() {
  301 + return speed;
  302 + }
  303 +
  304 + public void setSpeed(Float speed) {
  305 + this.speed = speed;
  306 + }
  307 +
  308 + public int getSource() {
  309 + return source;
  310 + }
  311 +
  312 + public void setSource(int source) {
  313 + this.source = source;
  314 + }
  315 +
  316 + public void offline(){
  317 + this.setAbnormalStatus("offline");
  318 + }
  319 +
  320 +/* public boolean isOnline(){
  321 + if(isOffline())
  322 + return false;
  323 +
  324 + long t = System.currentTimeMillis();
  325 +
  326 + if((t - this.getServerTimestamp()) > 1000 * 60 * 2){
  327 + return false;
  328 + }
  329 +
  330 + if((this.getServerTimestamp() - t) > 1000 * 60 * 3){
  331 + return false;
  332 + }
  333 + return true;
  334 + }*/
  335 +
  336 + /**
  337 + * 是否营运
  338 + * @return
  339 + */
  340 + public boolean isService(){
  341 + return state!=null && state==0;
  342 + }
  343 +
  344 + public boolean isOffline(){
  345 + return this.getAbnormalStatus() != null && this.getAbnormalStatus().equals("offline");
  346 + }
  347 +
  348 + public Long getServerTimestamp() {
  349 + return serverTimestamp;
  350 + }
  351 +
  352 + public void setServerTimestamp(Long serverTimestamp) {
  353 + this.serverTimestamp = serverTimestamp;
  354 + }
  355 +
  356 + public String getPremiseCode() {
  357 + return premiseCode;
  358 + }
  359 +
  360 + public void setPremiseCode(String premiseCode) {
  361 + this.premiseCode = premiseCode;
  362 + }
  363 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/PreconditionGeo.java
1   -package com.bsth.data.gpsdata_v2.entity;
2   -
3   -import com.bsth.util.Geo.Polygon;
4   -
5   -/**
6   - * 前置围栏 -地理坐标
7   - * Created by panzhao on 2017/9/23.
8   - */
9   -public class PreconditionGeo {
10   -
11   - private String name;
12   -
13   - /**
14   - * 前置约束的站点编码
15   - */
16   - private String stationCode;
17   -
18   - /**
19   - * 线路编码
20   - */
21   - private String lineCode;
22   -
23   - /**
24   - * 上下行
25   - */
26   - private int upDown;
27   -
28   - /**
29   - * 多边形坐标
30   - */
31   - private String coords;
32   -
33   - private com.bsth.util.Geo.Polygon polygon;
34   -
35   - private Integer order;
36   -
37   - public String getName() {
38   - return name;
39   - }
40   -
41   - public void setName(String name) {
42   - this.name = name;
43   - }
44   -
45   - public String getStationCode() {
46   - return stationCode;
47   - }
48   -
49   - public void setStationCode(String stationCode) {
50   - this.stationCode = stationCode;
51   - }
52   -
53   - public String getLineCode() {
54   - return lineCode;
55   - }
56   -
57   - public void setLineCode(String lineCode) {
58   - this.lineCode = lineCode;
59   - }
60   -
61   - public int getUpDown() {
62   - return upDown;
63   - }
64   -
65   - public void setUpDown(int upDown) {
66   - this.upDown = upDown;
67   - }
68   -
69   - public String getCoords() {
70   - return coords;
71   - }
72   -
73   - public void setCoords(String coords) {
74   - this.coords = coords;
75   - }
76   -
77   - public Integer getOrder() {
78   - return order;
79   - }
80   -
81   - public void setOrder(Integer order) {
82   - this.order = order;
83   - }
84   -
85   - public Polygon getPolygon() {
86   - return polygon;
87   - }
88   -
89   - public void setPolygon(Polygon polygon) {
90   - this.polygon = polygon;
91   - }
92   -}
  1 +package com.bsth.data.gpsdata_v2.entity;
  2 +
  3 +import com.bsth.util.Geo.Polygon;
  4 +
  5 +/**
  6 + * 前置围栏 -地理坐标
  7 + * Created by panzhao on 2017/9/23.
  8 + */
  9 +public class PreconditionGeo {
  10 +
  11 + private String name;
  12 +
  13 + /**
  14 + * 前置约束的站点编码
  15 + */
  16 + private String stationCode;
  17 +
  18 + /**
  19 + * 线路编码
  20 + */
  21 + private String lineCode;
  22 +
  23 + /**
  24 + * 上下行
  25 + */
  26 + private int upDown;
  27 +
  28 + /**
  29 + * 多边形坐标
  30 + */
  31 + private String coords;
  32 +
  33 + private com.bsth.util.Geo.Polygon polygon;
  34 +
  35 + private Integer order;
  36 +
  37 + public String getName() {
  38 + return name;
  39 + }
  40 +
  41 + public void setName(String name) {
  42 + this.name = name;
  43 + }
  44 +
  45 + public String getStationCode() {
  46 + return stationCode;
  47 + }
  48 +
  49 + public void setStationCode(String stationCode) {
  50 + this.stationCode = stationCode;
  51 + }
  52 +
  53 + public String getLineCode() {
  54 + return lineCode;
  55 + }
  56 +
  57 + public void setLineCode(String lineCode) {
  58 + this.lineCode = lineCode;
  59 + }
  60 +
  61 + public int getUpDown() {
  62 + return upDown;
  63 + }
  64 +
  65 + public void setUpDown(int upDown) {
  66 + this.upDown = upDown;
  67 + }
  68 +
  69 + public String getCoords() {
  70 + return coords;
  71 + }
  72 +
  73 + public void setCoords(String coords) {
  74 + this.coords = coords;
  75 + }
  76 +
  77 + public Integer getOrder() {
  78 + return order;
  79 + }
  80 +
  81 + public void setOrder(Integer order) {
  82 + this.order = order;
  83 + }
  84 +
  85 + public Polygon getPolygon() {
  86 + return polygon;
  87 + }
  88 +
  89 + public void setPolygon(Polygon polygon) {
  90 + this.polygon = polygon;
  91 + }
  92 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/StationRoute.java
1   -package com.bsth.data.gpsdata_v2.entity;
2   -
3   -import com.bsth.util.Geo.Point;
4   -import com.bsth.util.Geo.Polygon;
5   -
6   -/**
7   - * Created by panzhao on 2016/12/23.
8   - */
9   -public class StationRoute {
10   -
11   - /**
12   - * 线路编码
13   - */
14   - private String lineCode;
15   -
16   - /**
17   - * 上下行
18   - */
19   - private int directions;
20   -
21   - /**
22   - * 站点编码
23   - */
24   - private String code;
25   -
26   - /**
27   - * 路由顺序
28   - */
29   - private int routeSort;
30   -
31   - /**
32   - * 站点位置
33   - */
34   - private Point point;
35   -
36   - /**
37   - * 圆形半径
38   - */
39   - private Float radius;
40   -
41   - /**
42   - * 多边形电子围栏
43   - */
44   - private Polygon polygon;
45   -
46   - /**
47   - * 站点标记
48   - */
49   - private String mark;
50   -
51   - /**
52   - * 下一站
53   - */
54   - private StationRoute next;
55   -
56   - /**
57   - * 上一站
58   - */
59   - private StationRoute prve;
60   -
61   - private String name;
62   -
63   - /**
64   - * 是否有前置进站约束
65   - */
66   - private boolean premise;
67   -
68   - public String getCode() {
69   - return code;
70   - }
71   -
72   - public void setCode(String code) {
73   - this.code = code;
74   - }
75   -
76   - public int getRouteSort() {
77   - return routeSort;
78   - }
79   -
80   - public void setRouteSort(int routeSort) {
81   - this.routeSort = routeSort;
82   - }
83   -
84   - public Point getPoint() {
85   - return point;
86   - }
87   -
88   - public void setPoint(Point point) {
89   - this.point = point;
90   - }
91   -
92   - public Float getRadius() {
93   - return radius;
94   - }
95   -
96   - public void setRadius(Float radius) {
97   - this.radius = radius;
98   - }
99   -
100   - public Polygon getPolygon() {
101   - return polygon;
102   - }
103   -
104   - public void setPolygon(Polygon polygon) {
105   - this.polygon = polygon;
106   - }
107   -
108   - public String getLineCode() {
109   - return lineCode;
110   - }
111   -
112   - public void setLineCode(String lineCode) {
113   - this.lineCode = lineCode;
114   - }
115   -
116   - public int getDirections() {
117   - return directions;
118   - }
119   -
120   - public void setDirections(int directions) {
121   - this.directions = directions;
122   - }
123   -
124   - public StationRoute getNext() {
125   - return next;
126   - }
127   -
128   - public void setNext(StationRoute next) {
129   - this.next = next;
130   - }
131   -
132   - public StationRoute getPrve() {
133   - return prve;
134   - }
135   -
136   - public void setPrve(StationRoute prve) {
137   - this.prve = prve;
138   - }
139   -
140   - public String getMark() {
141   - return mark;
142   - }
143   -
144   - public void setMark(String mark) {
145   - this.mark = mark;
146   - }
147   -
148   - public String getName() {
149   - return name;
150   - }
151   -
152   - public void setName(String name) {
153   - this.name = name;
154   - }
155   -
156   - public boolean isPremise() {
157   - return premise;
158   - }
159   -
160   - public void setPremise(boolean premise) {
161   - this.premise = premise;
162   - }
163   -}
164   -
  1 +package com.bsth.data.gpsdata_v2.entity;
  2 +
  3 +import com.bsth.util.Geo.Point;
  4 +import com.bsth.util.Geo.Polygon;
  5 +
  6 +/**
  7 + * Created by panzhao on 2016/12/23.
  8 + */
  9 +public class StationRoute {
  10 +
  11 + /**
  12 + * 线路编码
  13 + */
  14 + private String lineCode;
  15 +
  16 + /**
  17 + * 上下行
  18 + */
  19 + private int directions;
  20 +
  21 + /**
  22 + * 站点编码
  23 + */
  24 + private String code;
  25 +
  26 + /**
  27 + * 路由顺序
  28 + */
  29 + private int routeSort;
  30 +
  31 + /**
  32 + * 站点位置
  33 + */
  34 + private Point point;
  35 +
  36 + /**
  37 + * 圆形半径
  38 + */
  39 + private Float radius;
  40 +
  41 + /**
  42 + * 多边形电子围栏
  43 + */
  44 + private Polygon polygon;
  45 +
  46 + /**
  47 + * 站点标记
  48 + */
  49 + private String mark;
  50 +
  51 + /**
  52 + * 下一站
  53 + */
  54 + private StationRoute next;
  55 +
  56 + /**
  57 + * 上一站
  58 + */
  59 + private StationRoute prve;
  60 +
  61 + private String name;
  62 +
  63 + /**
  64 + * 是否有前置进站约束
  65 + */
  66 + private boolean premise;
  67 +
  68 + public String getCode() {
  69 + return code;
  70 + }
  71 +
  72 + public void setCode(String code) {
  73 + this.code = code;
  74 + }
  75 +
  76 + public int getRouteSort() {
  77 + return routeSort;
  78 + }
  79 +
  80 + public void setRouteSort(int routeSort) {
  81 + this.routeSort = routeSort;
  82 + }
  83 +
  84 + public Point getPoint() {
  85 + return point;
  86 + }
  87 +
  88 + public void setPoint(Point point) {
  89 + this.point = point;
  90 + }
  91 +
  92 + public Float getRadius() {
  93 + return radius;
  94 + }
  95 +
  96 + public void setRadius(Float radius) {
  97 + this.radius = radius;
  98 + }
  99 +
  100 + public Polygon getPolygon() {
  101 + return polygon;
  102 + }
  103 +
  104 + public void setPolygon(Polygon polygon) {
  105 + this.polygon = polygon;
  106 + }
  107 +
  108 + public String getLineCode() {
  109 + return lineCode;
  110 + }
  111 +
  112 + public void setLineCode(String lineCode) {
  113 + this.lineCode = lineCode;
  114 + }
  115 +
  116 + public int getDirections() {
  117 + return directions;
  118 + }
  119 +
  120 + public void setDirections(int directions) {
  121 + this.directions = directions;
  122 + }
  123 +
  124 + public StationRoute getNext() {
  125 + return next;
  126 + }
  127 +
  128 + public void setNext(StationRoute next) {
  129 + this.next = next;
  130 + }
  131 +
  132 + public StationRoute getPrve() {
  133 + return prve;
  134 + }
  135 +
  136 + public void setPrve(StationRoute prve) {
  137 + this.prve = prve;
  138 + }
  139 +
  140 + public String getMark() {
  141 + return mark;
  142 + }
  143 +
  144 + public void setMark(String mark) {
  145 + this.mark = mark;
  146 + }
  147 +
  148 + public String getName() {
  149 + return name;
  150 + }
  151 +
  152 + public void setName(String name) {
  153 + this.name = name;
  154 + }
  155 +
  156 + public boolean isPremise() {
  157 + return premise;
  158 + }
  159 +
  160 + public void setPremise(boolean premise) {
  161 + this.premise = premise;
  162 + }
  163 +}
  164 +
... ...
src/main/java/com/bsth/data/gpsdata_v2/entity/trail/GpsExecTrail.java
1   -package com.bsth.data.gpsdata_v2.entity.trail;
2   -
3   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
4   -
5   -import java.util.LinkedList;
6   -
7   -/**
8   - * GPS 班次执行轨迹,过程数据
9   - * Created by panzhao on 2017/11/16.
10   - */
11   -public class GpsExecTrail {
12   -
13   - /**
14   - * 执行的班次ID
15   - */
16   - private Long schId;
17   -
18   - /**
19   - * 实际经过的站点路由
20   - */
21   - private LinkedList<GpsEntity> srs = new LinkedList<>();
22   -
23   - /**
24   - * 车辆编码
25   - */
26   - private String nbbm;
27   -
28   - /**
29   - * 是否结束
30   - */
31   - private boolean end;
32   -
33   - public Long getSchId() {
34   - return schId;
35   - }
36   -
37   - public void setSchId(Long schId) {
38   - this.schId = schId;
39   - }
40   -
41   - public LinkedList<GpsEntity> getSrs() {
42   - return srs;
43   - }
44   -
45   - public void setSrs(LinkedList<GpsEntity> srs) {
46   - this.srs = srs;
47   - }
48   -
49   - public String getNbbm() {
50   - return nbbm;
51   - }
52   -
53   - public void setNbbm(String nbbm) {
54   - this.nbbm = nbbm;
55   - }
56   -
57   - public boolean isEnd() {
58   - return end;
59   - }
60   -
61   - public void setEnd(boolean end) {
62   - this.end = end;
63   - }
64   -}
  1 +package com.bsth.data.gpsdata_v2.entity.trail;
  2 +
  3 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  4 +
  5 +import java.util.LinkedList;
  6 +
  7 +/**
  8 + * GPS 班次执行轨迹,过程数据
  9 + * Created by panzhao on 2017/11/16.
  10 + */
  11 +public class GpsExecTrail {
  12 +
  13 + /**
  14 + * 执行的班次ID
  15 + */
  16 + private Long schId;
  17 +
  18 + /**
  19 + * 实际经过的站点路由
  20 + */
  21 + private LinkedList<GpsEntity> srs = new LinkedList<>();
  22 +
  23 + /**
  24 + * 车辆编码
  25 + */
  26 + private String nbbm;
  27 +
  28 + /**
  29 + * 是否结束
  30 + */
  31 + private boolean end;
  32 +
  33 + public Long getSchId() {
  34 + return schId;
  35 + }
  36 +
  37 + public void setSchId(Long schId) {
  38 + this.schId = schId;
  39 + }
  40 +
  41 + public LinkedList<GpsEntity> getSrs() {
  42 + return srs;
  43 + }
  44 +
  45 + public void setSrs(LinkedList<GpsEntity> srs) {
  46 + this.srs = srs;
  47 + }
  48 +
  49 + public String getNbbm() {
  50 + return nbbm;
  51 + }
  52 +
  53 + public void setNbbm(String nbbm) {
  54 + this.nbbm = nbbm;
  55 + }
  56 +
  57 + public boolean isEnd() {
  58 + return end;
  59 + }
  60 +
  61 + public void setEnd(boolean end) {
  62 + this.end = end;
  63 + }
  64 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/AbnormalStateProcess.java
1   -package com.bsth.data.gpsdata_v2.handlers;
2   -
3   -import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
4   -import com.bsth.data.gpsdata_v2.entity.CtLineString;
5   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
6   -import com.bsth.data.gpsdata_v2.utils.GeoUtils;
7   -import com.bsth.util.Geo.Point;
8   -import org.springframework.stereotype.Component;
9   -
10   -import java.util.List;
11   -
12   -/**
13   - * 越界/超速 判断
14   - * Created by panzhao on 2017/11/16.
15   - */
16   -@Component
17   -public class AbnormalStateProcess {
18   -
19   - /**
20   - * 默认限速
21   - */
22   - private static final double DEFAULT_SPEED_LIMIT = 60;
23   - /**
24   - * 越界阈值
25   - */
26   - private static final double OUT_BOUNDS_THRESHOLD = 100;
27   -
28   -
29   - public void process(GpsEntity gps) {
30   - if(isOffline(gps))
31   - return;
32   -
33   - if(overspeed(gps))
34   - return;
35   -
36   - if(outOfBounds((gps)))
37   - return;
38   - }
39   -
40   - private boolean isOffline(GpsEntity gps){
41   - return gps.getAbnormalStatus() != null && gps.getAbnormalStatus().equals("offline");
42   - }
43   -
44   -
45   - /**
46   - * 是否超速
47   - * @param gps
48   - * @return
49   - */
50   - private boolean overspeed(GpsEntity gps){
51   - double maxSpeed = DEFAULT_SPEED_LIMIT;
52   - if(GeoCacheData.speedLimit(gps.getLineId()) != null)
53   - maxSpeed = GeoCacheData.speedLimit(gps.getLineId());
54   -
55   - if(gps.getSpeed() > maxSpeed){
56   - gps.setAbnormalStatus("overspeed");
57   - return true;
58   - }
59   - return false;
60   - }
61   -
62   -
63   - /**
64   - * 是否越界
65   - * @param gps
66   - * @return
67   - */
68   - public boolean outOfBounds(GpsEntity gps){
69   - //只处理场站外的车
70   - if(gps.getInstation() != 0){
71   - return false;
72   - }
73   -
74   - List<CtLineString> list = GeoCacheData.getLineStringList(gps);
75   - Point point = new Point(gps.getLon(), gps.getLat());
76   -
77   - double min = -1, distance;
78   -
79   - for(CtLineString lineString : list){
80   - distance = GeoUtils.getDistanceFromLine(lineString.getS(),lineString.getE(), point);
81   -
82   - if(min == -1 || min > distance)
83   - min = distance;
84   - }
85   -
86   - gps.setOutOfBoundDistance(min);
87   - if(min > OUT_BOUNDS_THRESHOLD){
88   - gps.setAbnormalStatus("outBounds");
89   - return true;
90   - }
91   - return false;
92   - }
93   -}
  1 +package com.bsth.data.gpsdata_v2.handlers;
  2 +
  3 +import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
  4 +import com.bsth.data.gpsdata_v2.entity.CtLineString;
  5 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  6 +import com.bsth.data.gpsdata_v2.utils.GeoUtils;
  7 +import com.bsth.util.Geo.Point;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 越界/超速 判断
  14 + * Created by panzhao on 2017/11/16.
  15 + */
  16 +@Component
  17 +public class AbnormalStateProcess {
  18 +
  19 + /**
  20 + * 默认限速
  21 + */
  22 + private static final double DEFAULT_SPEED_LIMIT = 60;
  23 + /**
  24 + * 越界阈值
  25 + */
  26 + private static final double OUT_BOUNDS_THRESHOLD = 100;
  27 +
  28 +
  29 + public void process(GpsEntity gps) {
  30 + if(isOffline(gps))
  31 + return;
  32 +
  33 + if(overspeed(gps))
  34 + return;
  35 +
  36 + if(outOfBounds((gps)))
  37 + return;
  38 + }
  39 +
  40 + private boolean isOffline(GpsEntity gps){
  41 + return gps.getAbnormalStatus() != null && gps.getAbnormalStatus().equals("offline");
  42 + }
  43 +
  44 +
  45 + /**
  46 + * 是否超速
  47 + * @param gps
  48 + * @return
  49 + */
  50 + private boolean overspeed(GpsEntity gps){
  51 + double maxSpeed = DEFAULT_SPEED_LIMIT;
  52 + if(GeoCacheData.speedLimit(gps.getLineId()) != null)
  53 + maxSpeed = GeoCacheData.speedLimit(gps.getLineId());
  54 +
  55 + if(gps.getSpeed() > maxSpeed){
  56 + gps.setAbnormalStatus("overspeed");
  57 + return true;
  58 + }
  59 + return false;
  60 + }
  61 +
  62 +
  63 + /**
  64 + * 是否越界
  65 + * @param gps
  66 + * @return
  67 + */
  68 + public boolean outOfBounds(GpsEntity gps){
  69 + //只处理场站外的车
  70 + if(gps.getInstation() != 0){
  71 + return false;
  72 + }
  73 +
  74 + List<CtLineString> list = GeoCacheData.getLineStringList(gps);
  75 + Point point = new Point(gps.getLon(), gps.getLat());
  76 +
  77 + double min = -1, distance;
  78 +
  79 + for(CtLineString lineString : list){
  80 + distance = GeoUtils.getDistanceFromLine(lineString.getS(),lineString.getE(), point);
  81 +
  82 + if(min == -1 || min > distance)
  83 + min = distance;
  84 + }
  85 +
  86 + gps.setOutOfBoundDistance(min);
  87 + if(min > OUT_BOUNDS_THRESHOLD){
  88 + gps.setAbnormalStatus("outBounds");
  89 + return true;
  90 + }
  91 + return false;
  92 + }
  93 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/GpsStateProcess.java
1   -package com.bsth.data.gpsdata_v2.handlers;
2   -
3   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
4   -import com.bsth.data.gpsdata_v2.status_manager.GpsStatusManager;
5   -import com.bsth.data.schedule.DayOfSchedule;
6   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
7   -import org.springframework.beans.factory.annotation.Autowired;
8   -import org.springframework.stereotype.Component;
9   -
10   -/**
11   - * GPS 状态处理
12   - * Created by panzhao on 2017/11/15.
13   - */
14   -@Component
15   -public class GpsStateProcess {
16   -
17   - @Autowired
18   - DayOfSchedule dayOfSchedule;
19   -
20   - @Autowired
21   - GpsStatusManager gpsStatusManager;
22   -
23   - public void process(GpsEntity gps){
24   - //在执行的任务
25   - ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
26   -
27   - if(null == sch)
28   - return;
29   -
30   - byte upDown = Byte.parseByte(sch.getXlDir());
31   -
32   - if(gps.getUpDown() != upDown){
33   - gps.setUpDown(upDown);//修正走向
34   - }
35   -
36   - if((!gps.isService() || gps.getUpDown() != upDown) &&
37   - !dayOfSchedule.emptyService(sch)){
38   - //下发指令纠正车载的 营运状态 和 走向
39   - gpsStatusManager.changeServiceState(gps.getNbbm(), upDown, 0, "同步@系统");
40   - }
41   -
42   - if(!sch.getXlBm().equals(gps.getLineId())){
43   - //切换车载的 线路编码
44   - gpsStatusManager.changeLine(gps.getNbbm(), sch.getXlBm(), "同步@系统");
45   - }
46   - }
47   -}
  1 +package com.bsth.data.gpsdata_v2.handlers;
  2 +
  3 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  4 +import com.bsth.data.gpsdata_v2.status_manager.GpsStatusManager;
  5 +import com.bsth.data.schedule.DayOfSchedule;
  6 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +/**
  11 + * GPS 状态处理
  12 + * Created by panzhao on 2017/11/15.
  13 + */
  14 +@Component
  15 +public class GpsStateProcess {
  16 +
  17 + @Autowired
  18 + DayOfSchedule dayOfSchedule;
  19 +
  20 + @Autowired
  21 + GpsStatusManager gpsStatusManager;
  22 +
  23 + public void process(GpsEntity gps){
  24 + //在执行的任务
  25 + ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
  26 +
  27 + if(null == sch)
  28 + return;
  29 +
  30 + byte upDown = Byte.parseByte(sch.getXlDir());
  31 +
  32 + if(gps.getUpDown() != upDown){
  33 + gps.setUpDown(upDown);//修正走向
  34 + }
  35 +
  36 + if((!gps.isService() || gps.getUpDown() != upDown) &&
  37 + !dayOfSchedule.emptyService(sch)){
  38 + //下发指令纠正车载的 营运状态 和 走向
  39 + gpsStatusManager.changeServiceState(gps.getNbbm(), upDown, 0, "同步@系统");
  40 + }
  41 +
  42 + if(!sch.getXlBm().equals(gps.getLineId())){
  43 + //切换车载的 线路编码
  44 + gpsStatusManager.changeLine(gps.getNbbm(), sch.getXlBm(), "同步@系统");
  45 + }
  46 + }
  47 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/InStationProcess.java
... ... @@ -42,40 +42,56 @@ public class InStationProcess {
42 42  
43 43 Logger logger = LoggerFactory.getLogger(this.getClass());
44 44  
45   - public void process(GpsEntity gps){
  45 + public void process(GpsEntity gps) {
46 46 GpsEntity prev = GpsCacheData.getPrev(gps);
47 47  
48   - if(isInsideStation(gps) &&
49   - (prev == null || !isInsideStation(prev) || !prev.getStopNo().equals(gps.getStopNo()))){
50   - inStation(gps, prev); //进站
  48 + if(null == prev)
  49 + return;
  50 +
  51 + //从站外到站内
  52 + if(prev.getInstation() == 0 && gps.getInstation() > 0){
  53 + inStation(gps, prev);
  54 + }
  55 +
  56 + //从站内到另一个站内
  57 + if(prev.getInstation() == 1 && gps.getInstation() == 1
  58 + && !prev.getStopNo().equals(gps.getStopNo())
  59 + && !prev.getStation().getName().equals(gps.getStation().getName()))
  60 + inStation(gps, prev);
  61 +
  62 + //从场内到站内
  63 + if(prev.getInstation() == 2 && gps.getInstation() == 1){
  64 + inStation(gps, prev);
51 65 }
52   - }
53 66  
54   - private boolean isInsideStation(GpsEntity gps){
55   - return gps.getInstation() >= 1;
  67 + //被起点站覆盖的情况下进场
  68 + if(isInPark(gps, prev))
  69 + inStation(gps, prev);
56 70 }
57 71  
58 72 /**
59 73 * 进站
  74 + *
60 75 * @param gps
61 76 * @param prev
62 77 */
63   - private void inStation(GpsEntity gps, GpsEntity prev){
64   - boolean flow=true;
  78 + private void inStation(GpsEntity gps, GpsEntity prev) {
  79 + boolean flow = true;
65 80 //要经过一个中途站才能进
66 81 StationRoute s = GpsCacheData.prevStation(gps);
67 82 List<StationRoute> routes = GeoCacheData.getStationRoute(gps.getLineId(), gps.getUpDown());
68   - if(routes.size() > 3 && null != s && s.getName().equals(gps.getStation().getName())){
  83 + if (gps.getInstation() == 1 && routes.size() > 3
  84 + && null != s && s.getName().equals(gps.getStation().getName())) {
69 85 logger.info("没有进中途站,拒绝进站... -" + gps.getNbbm() + " -time:" + gps.getTimestamp());
70 86 flow = false;
71 87 }
72 88  
73 89  
74 90 ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
75   - boolean isEnd=false;
  91 + boolean isEnd = false;
76 92  
77 93 //进终点
78   - if(flow && null != sch && sch.getZdzCode().equals(gps.getStopNo())){
  94 + if (flow && null != sch && sch.getZdzCode().equals(gps.getStopNo())) {
79 95 inEndStation(sch, gps);
80 96 isEnd = true;
81 97 }
... ... @@ -85,16 +101,17 @@ public class InStationProcess {
85 101  
86 102 /**
87 103 * 进班次终点
  104 + *
88 105 * @param gps
89 106 */
90 107 private void inEndStation(ScheduleRealInfo sch, GpsEntity gps) {
91 108 String nbbm = sch.getClZbh();
92 109 //校验进站前置约束
93   - if(!validInPremise(gps))
  110 + if (!validInPremise(gps))
94 111 return;
95 112  
96 113 //实达时间不覆盖
97   - if(StringUtils.isNotEmpty(sch.getZdsjActual()))
  114 + if (StringUtils.isNotEmpty(sch.getZdsjActual()))
98 115 return;
99 116  
100 117 //应用到离站缓冲区设置参数
... ... @@ -110,14 +127,14 @@ public class InStationProcess {
110 127  
111 128 //车辆的下一个班次
112 129 ScheduleRealInfo next = dayOfSchedule.next(sch);
113   - if(next != null){
  130 + if (next != null) {
114 131 dayOfSchedule.addExecPlan(next);
115 132 inStationAndInPark(sch, next);//进站既进场
116 133 }
117 134  
118 135 //路牌的下一个班次,页面显示起点实际到达时间
119 136 ScheduleRealInfo lpNext = dayOfSchedule.nextByLp(sch);
120   - if(lpNext != null){
  137 + if (lpNext != null) {
121 138 lpNext.setQdzArrDatesj(sch.getZdsjActual());
122 139 }
123 140  
... ... @@ -138,33 +155,35 @@ public class InStationProcess {
138 155 DirectivePushQueue.put6002(next, doneSum, "到站@系统");
139 156  
140 157 //套跑 -下发线路切换指令
141   - if(null != next && !next.getXlBm().equals(sch.getXlBm())){
  158 + if (null != next && !next.getXlBm().equals(sch.getXlBm())) {
142 159 gpsStatusManager.changeLine(next.getClZbh(), next.getXlBm(), "套跑@系统");
143 160 }
144 161  
145   - if(null == next && gps.isService())
146   - nonService(sch, "结束@系统");//班次结束
147   - else if(dayOfSchedule.emptyService(next))
148   - nonService(sch, "空驶@系统");//下一班非营运
  162 + if(null == next){
  163 + if (gps.isService())
  164 + nonService(sch, "结束@系统");//班次结束
  165 + else if (dayOfSchedule.emptyService(next))
  166 + nonService(sch, "空驶@系统");//下一班非营运
  167 + }
149 168 }
150 169  
151 170 /**
152 171 * 校验进站前置约束
  172 + *
153 173 * @param gps
154 174 * @return
155 175 */
156 176 private boolean validInPremise(GpsEntity gps) {
157 177 StationRoute sr = gps.getStation();
158   - if(null == sr || !sr.isPremise())
  178 + if (null == sr || !sr.isPremise())
159 179 return true;
160 180  
161 181 String premiseCode = gps.getPremiseCode();
162 182  
163   - if(StringUtils.isNotEmpty(premiseCode) && premiseCode.equals(gps.getStopNo())){
  183 + if (StringUtils.isNotEmpty(premiseCode) && premiseCode.equals(gps.getStopNo())) {
164 184 logger.info("满足前置进站约束 " + premiseCode);
165 185 return true;
166   - }
167   - else{
  186 + } else {
168 187 logger.info(gps.getNbbm() + " not premiseCode 不满足前置进站约束 " + premiseCode);
169 188 }
170 189 return false;
... ... @@ -172,9 +191,10 @@ public class InStationProcess {
172 191  
173 192 /**
174 193 * 进站既进场
  194 + *
175 195 * @param sch
176 196 */
177   - private void inStationAndInPark(ScheduleRealInfo sch, ScheduleRealInfo next){
  197 + private void inStationAndInPark(ScheduleRealInfo sch, ScheduleRealInfo next) {
178 198 LineConfig config = lineConfigData.get(sch.getXlBm());
179 199 //限定出站既出场的停车场
180 200 String park = config.getTwinsPark();
... ... @@ -191,7 +211,7 @@ public class InStationProcess {
191 211  
192 212 //分班的时候,需要再跳过1个班次
193 213 next = dayOfSchedule.next(next);
194   - if(next != null)
  214 + if (next != null)
195 215 dayOfSchedule.addExecPlan(next);
196 216  
197 217 //进场,切换成非营运状态
... ... @@ -200,27 +220,28 @@ public class InStationProcess {
200 220 }
201 221  
202 222  
203   - private boolean isEmptyMileage(ScheduleRealInfo sch){
204   - return sch.getBcsj()==0 || sch.getJhlcOrig().intValue()==0;
  223 + private boolean isEmptyMileage(ScheduleRealInfo sch) {
  224 + return sch.getBcsj() == 0 || sch.getJhlcOrig().intValue() == 0;
205 225 }
206 226  
207 227  
208 228 /**
209 229 * 切换为非营运状态
  230 + *
210 231 * @param sch
211 232 * @param sender
212 233 */
213   - private void nonService(ScheduleRealInfo sch, String sender){
  234 + private void nonService(ScheduleRealInfo sch, String sender) {
214 235 gpsStatusManager.changeServiceState(sch.getClZbh(), sch.getXlDir(), 1, sender);
215 236 }
216 237  
217   - private void endSch(ScheduleRealInfo sch, Long t){
  238 + private void endSch(ScheduleRealInfo sch, Long t) {
218 239 sch.setFcsjActualAll(t);
219 240 sch.setZdsjActualAll(t);
220 241 }
221 242  
222 243 private void transformUpDown(GpsEntity gps, ScheduleRealInfo sch) {
223   - if(null == sch)
  244 + if (null == sch)
224 245 return;
225 246 byte upDown = Byte.parseByte(sch.getXlDir());
226 247 //gps 切换走向
... ... @@ -233,4 +254,10 @@ public class InStationProcess {
233 254 gps.setStopNo(station.getCode());
234 255 }
235 256 }
236   -}
  257 +
  258 + private boolean isInPark(GpsEntity gps, GpsEntity prve){
  259 + if(StringUtils.isNotEmpty(gps.getCarparkNo()) && StringUtils.isEmpty(prve.getCarparkNo()))
  260 + return true;
  261 + return false;
  262 + }
  263 +}
237 264 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/OutStationProcess.java
... ... @@ -4,6 +4,7 @@ import com.bsth.data.LineConfigData;
4 4 import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
5 5 import com.bsth.data.gpsdata_v2.entity.GpsEntity;
6 6 import com.bsth.data.gpsdata_v2.status_manager.GpsStatusManager;
  7 +import com.bsth.data.gpsdata_v2.utils.SignalSchPlanMatcher;
7 8 import com.bsth.data.schedule.DayOfSchedule;
8 9 import com.bsth.data.schedule.late_adjust.LateAdjustHandle;
9 10 import com.bsth.entity.realcontrol.LineConfig;
... ... @@ -34,28 +35,53 @@ public class OutStationProcess {
34 35 SendUtils sendUtils;
35 36  
36 37 @Autowired
  38 + SignalSchPlanMatcher signalSchPlanMatcher;
  39 +
  40 + @Autowired
37 41 GpsStatusManager gpsStatusManager;
  42 + private final static int MAX_BEFORE_TIME = 1000 * 60 * 120;
38 43  
39 44 public void process(GpsEntity gps){
40 45 GpsEntity prev = GpsCacheData.getPrev(gps);
41   - if(gps.getInstation()==0 && prev!=null && isInsideStation(prev)){
42   - outStation(gps); //出站
43   - }
44   - }
45 46  
46   - private boolean isInsideStation(GpsEntity gps){
47   - return gps.getInstation() >= 1;
  47 + if(null == prev)
  48 + return;
  49 +
  50 + //从站内到站外
  51 + if(prev.getInstation() > 0 && gps.getInstation() == 0)
  52 + outStation(gps, prev);
  53 +
  54 + //从站内到另一个站内
  55 + if(prev.getInstation() > 0 && gps.getInstation() > 0
  56 + && !prev.getStopNo().equals(gps.getStopNo()))
  57 + outStation(gps, prev);
  58 +
  59 + //在被起点站覆盖的情况下出场
  60 + if(isOutPark(gps, prev))
  61 + outStation(gps, prev);
48 62 }
49 63  
50 64 /**
51 65 * 出站
52 66 * @param gps
53 67 */
54   - private void outStation(GpsEntity gps) {
  68 + private void outStation(GpsEntity gps, GpsEntity prev) {
55 69 ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
56 70  
57 71 //起点发车
58   - if (null != sch && sch.getQdzCode().equals(gps.getStopNo())){
  72 + if (null != sch &&
  73 + (sch.getQdzCode().equals(prev.getStopNo()) || sch.getQdzCode().equals(prev.getCarparkNo()))){
  74 + //发车班次匹配
  75 + if(!signalSchPlanMatcher.outMatch(gps, sch)){
  76 + //outStation(gps);
  77 + return;
  78 + }
  79 +
  80 + int diff = (int) (sch.getDfsjT() - gps.getTimestamp());
  81 + //首班出场最多提前2小时
  82 + if((dayOfSchedule.isFirstOut(sch) && diff > MAX_BEFORE_TIME) || diff > MAX_BEFORE_TIME / 2)
  83 + return;
  84 +
59 85 gps.setPremiseCode(null);//清除前置围栏标记
60 86  
61 87 if(StringUtils.isNotEmpty(sch.getFcsjActual())
... ... @@ -113,6 +139,10 @@ public class OutStationProcess {
113 139 if(Math.abs(t2 - c) < threshold && c - t1 > threshold){
114 140 return true;
115 141 }
  142 +
  143 + if(c - t1 > 1000 * 60 * 60 * 2 && Math.abs(t2 - c) < c - t1){
  144 + return true;
  145 + }
116 146 return false;
117 147 }
118 148  
... ... @@ -155,4 +185,10 @@ public class OutStationProcess {
155 185 sch.setFcsjActualAll(t);
156 186 sch.setZdsjActualAll(t);
157 187 }
158   -}
  188 +
  189 + private boolean isOutPark(GpsEntity gps, GpsEntity prve){
  190 + if(StringUtils.isNotEmpty(prve.getCarparkNo()) && StringUtils.isEmpty(gps.getCarparkNo()))
  191 + return true;
  192 + return false;
  193 + }
  194 +}
159 195 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/ReverseRouteProcess.java
1   -package com.bsth.data.gpsdata_v2.handlers;
2   -
3   -import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
4   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
5   -import com.bsth.data.gpsdata_v2.entity.StationRoute;
6   -import com.bsth.data.schedule.DayOfSchedule;
7   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
8   -import org.springframework.beans.factory.annotation.Autowired;
9   -import org.springframework.stereotype.Component;
10   -
11   -import java.util.List;
12   -
13   -/**
14   - * 反向路由处理(进站的时候处理)
15   - * Created by panzhao on 2017/11/20.
16   - */
17   -@Component
18   -public class ReverseRouteProcess {
19   -
20   - private static final int REVER_THRESHOLD = 3;
21   -
22   - private static final long TIME_THRESHOLD = 1000 * 60 * 120;
23   -
24   - @Autowired
25   - DayOfSchedule dayOfSchedule;
26   -
27   - public void process(GpsEntity gps){
28   - if(reversRoute(gps)){
29   - ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
30   - if(isInOut(sch) || !sch.getXlBm().equals(gps.getLineId()))
31   - return;
32   -
33   - //next
34   - ScheduleRealInfo next = dayOfSchedule.next(sch);
35   - if(isInOut(next))
36   - return;
37   -
38   - //跳下一个班次
39   - if(Math.abs(next.getDfsjT() - gps.getTimestamp()) < TIME_THRESHOLD)
40   - dayOfSchedule.addExecPlan(next);
41   - }
42   - }
43   -
44   - private boolean reversRoute(GpsEntity gps) {
45   - if(gps.getInstation() != 1)
46   - return false;
47   -
48   - int sortNo = gps.getStation().getRouteSort();
49   - StationRoute prev = GpsCacheData.prevStation(gps);
50   - //和上一个站点是反向
51   - if(null != prev && sortNo < prev.getRouteSort()){
52   -
53   - //满足3个进站反向信号
54   - List<StationRoute> prevs = GpsCacheData.prevMultiStation(gps);
55   -
56   - int count = 0;
57   - for(StationRoute s : prevs){
58   - if(sortNo < s.getRouteSort())
59   - count ++;
60   - sortNo = s.getRouteSort();
61   - }
62   -
63   - if(count >= REVER_THRESHOLD)
64   - return true;
65   - }
66   -
67   - return false;
68   - }
69   -
70   - private boolean isInOut(ScheduleRealInfo sch){
71   - return sch.getBcType().equals("in") || sch.getBcType().equals("out");
72   - }
73   -}
  1 +package com.bsth.data.gpsdata_v2.handlers;
  2 +
  3 +import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
  4 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  5 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  6 +import com.bsth.data.schedule.DayOfSchedule;
  7 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 反向路由处理(进站的时候处理)
  15 + * Created by panzhao on 2017/11/20.
  16 + */
  17 +@Component
  18 +public class ReverseRouteProcess {
  19 +
  20 + private static final int REVER_THRESHOLD = 3;
  21 +
  22 + private static final long TIME_THRESHOLD = 1000 * 60 * 120;
  23 +
  24 + @Autowired
  25 + DayOfSchedule dayOfSchedule;
  26 +
  27 + public void process(GpsEntity gps){
  28 + if(reversRoute(gps)){
  29 + ScheduleRealInfo sch = dayOfSchedule.executeCurr(gps.getNbbm());
  30 + if(isInOut(sch) || !sch.getXlBm().equals(gps.getLineId()))
  31 + return;
  32 +
  33 + //next
  34 + ScheduleRealInfo next = dayOfSchedule.next(sch);
  35 + if(isInOut(next))
  36 + return;
  37 +
  38 + //跳下一个班次
  39 + if(Math.abs(next.getDfsjT() - gps.getTimestamp()) < TIME_THRESHOLD)
  40 + dayOfSchedule.addExecPlan(next);
  41 + }
  42 + }
  43 +
  44 + private boolean reversRoute(GpsEntity gps) {
  45 + if(gps.getInstation() != 1)
  46 + return false;
  47 +
  48 + int sortNo = gps.getStation().getRouteSort();
  49 + StationRoute prev = GpsCacheData.prevStation(gps);
  50 + //和上一个站点是反向
  51 + if(null != prev && sortNo < prev.getRouteSort()){
  52 +
  53 + //满足3个进站反向信号
  54 + List<StationRoute> prevs = GpsCacheData.prevMultiStation(gps);
  55 +
  56 + int count = 0;
  57 + for(StationRoute s : prevs){
  58 + if(sortNo < s.getRouteSort())
  59 + count ++;
  60 + sortNo = s.getRouteSort();
  61 + }
  62 +
  63 + if(count >= REVER_THRESHOLD)
  64 + return true;
  65 + }
  66 +
  67 + return false;
  68 + }
  69 +
  70 + private boolean isInOut(ScheduleRealInfo sch){
  71 + return sch.getBcType().equals("in") || sch.getBcType().equals("out");
  72 + }
  73 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/StationInsideProcess.java
1   -package com.bsth.data.gpsdata_v2.handlers;
2   -
3   -import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
4   -import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
5   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
6   -import com.bsth.data.gpsdata_v2.entity.StationRoute;
7   -import com.bsth.data.gpsdata_v2.utils.GeoUtils;
8   -import org.springframework.stereotype.Component;
9   -
10   -import java.util.List;
11   -
12   -/**
13   - * 站内 场内判定
14   - * Created by panzhao on 2017/11/16.
15   - */
16   -@Component
17   -public class StationInsideProcess {
18   -
19   - public void process(GpsEntity gps){
20   - //是否在场内
21   - String parkCode = GeoUtils.gpsInCarpark(gps);
22   -
23   - if (parkCode != null) {
24   - gps.setInstation(2);
25   - gps.setStopNo(parkCode);
26   - gps.setCarparkNo(parkCode);
27   - }
28   -
29   - //是否在站内
30   - List<StationRoute> srs = GeoCacheData.getStationRoute(gps.getLineId(), gps.getUpDown());
31   - StationRoute station = GeoUtils.gpsInStation(gps, srs);
32   - if (station != null) {
33   - gps.setInstation(1);
34   - gps.setStopNo(station.getCode());
35   - gps.setStation(station);
36   - }
37   -
38   - //是否在进站前置围栏内
39   - String premiseCode = GeoUtils.gpsInPremiseGeo(gps);
40   - gps.setPremiseCode(premiseCode);
41   -
42   - //上一个点位
43   - GpsEntity prev = GpsCacheData.getPrev(gps);
44   -
45   - if(null != prev){
46   - //继承前置围栏状态
47   - if(null == premiseCode && null != prev.getPremiseCode())
48   - gps.setPremiseCode(prev.getPremiseCode());
49   -
50   - //在场,站外
51   - if(gps.getInstation() == 0){
52   - gps.setStopNo(prev.getStopNo());//继承上一个点的站点编码
53   - }
54   - }
55   - }
56   -}
  1 +package com.bsth.data.gpsdata_v2.handlers;
  2 +
  3 +import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
  4 +import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
  5 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  6 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  7 +import com.bsth.data.gpsdata_v2.utils.GeoUtils;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 站内 场内判定
  14 + * Created by panzhao on 2017/11/16.
  15 + */
  16 +@Component
  17 +public class StationInsideProcess {
  18 +
  19 + public void process(GpsEntity gps){
  20 + //是否在场内
  21 + String parkCode = GeoUtils.gpsInCarpark(gps);
  22 +
  23 + if (parkCode != null) {
  24 + gps.setInstation(2);
  25 + gps.setStopNo(parkCode);
  26 + gps.setCarparkNo(parkCode);
  27 + }
  28 +
  29 + //是否在站内
  30 + List<StationRoute> srs = GeoCacheData.getStationRoute(gps.getLineId(), gps.getUpDown());
  31 + StationRoute station = GeoUtils.gpsInStation(gps, srs);
  32 + if (station != null) {
  33 + gps.setInstation(1);
  34 + gps.setStopNo(station.getCode());
  35 + gps.setStation(station);
  36 + }
  37 +
  38 + //是否在进站前置围栏内
  39 + String premiseCode = GeoUtils.gpsInPremiseGeo(gps);
  40 + gps.setPremiseCode(premiseCode);
  41 +
  42 + //上一个点位
  43 + GpsEntity prev = GpsCacheData.getPrev(gps);
  44 +
  45 + if(null != prev){
  46 + //继承前置围栏状态
  47 + if(null == premiseCode && null != prev.getPremiseCode())
  48 + gps.setPremiseCode(prev.getPremiseCode());
  49 +
  50 + //在场,站外
  51 + if(gps.getInstation() == 0){
  52 + gps.setStopNo(prev.getStopNo());//继承上一个点的站点编码
  53 + }
  54 + }
  55 + }
  56 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/load/GatewayHttpLoader.java
1   -package com.bsth.data.gpsdata_v2.load;
2   -
3   -import com.alibaba.fastjson.JSON;
4   -import com.bsth.data.BasicData;
5   -import com.bsth.data.gpsdata_v2.GpsRealData;
6   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
7   -import com.bsth.data.gpsdata_v2.utils.GpsDataUtils;
8   -import com.bsth.util.ConfigUtil;
9   -import org.apache.commons.lang3.StringUtils;
10   -import org.apache.http.HttpEntity;
11   -import org.apache.http.client.config.RequestConfig;
12   -import org.apache.http.client.methods.CloseableHttpResponse;
13   -import org.apache.http.client.methods.HttpGet;
14   -import org.apache.http.impl.client.CloseableHttpClient;
15   -import org.apache.http.impl.client.HttpClients;
16   -import org.slf4j.Logger;
17   -import org.slf4j.LoggerFactory;
18   -import org.springframework.beans.BeansException;
19   -import org.springframework.context.ApplicationContext;
20   -import org.springframework.context.ApplicationContextAware;
21   -import org.springframework.stereotype.Component;
22   -
23   -import java.io.BufferedReader;
24   -import java.io.InputStreamReader;
25   -import java.util.ArrayList;
26   -import java.util.List;
27   -
28   -/**
29   - * 从网关http 接口加载数据
30   - * Created by panzhao on 2017/11/15.
31   - */
32   -@Component
33   -public class GatewayHttpLoader implements ApplicationContextAware{
34   -
35   - static Logger logger = LoggerFactory.getLogger(GatewayHttpLoader.class);
36   -
37   - static String url;
38   - static List<GpsEntity> list;
39   - static CloseableHttpClient httpClient = null;
40   - static HttpGet get;
41   - static RequestConfig requestConfig;
42   - static CloseableHttpResponse response;
43   - static HttpEntity entity;
44   - static BufferedReader br;
45   -
46   - static GpsRealData gpsRealData;
47   -
48   - static{
49   - url = ConfigUtil.get("http.gps.real.url");
50   - list = new ArrayList<>();
51   - httpClient = HttpClients.createDefault();
52   - get = new HttpGet(url);
53   - requestConfig = RequestConfig.custom()
54   - .setConnectTimeout(1500).setConnectionRequestTimeout(1000)
55   - .setSocketTimeout(1500).build();
56   - get.setConfig(requestConfig);
57   - }
58   -
59   - public static List<GpsEntity> load(){
60   - try{
61   - if(list.size() > 0)
62   - list.clear();
63   -
64   - response = httpClient.execute(get);
65   - entity = response.getEntity();
66   -
67   - if(null == entity)
68   - return list;
69   -
70   - br = new BufferedReader(new InputStreamReader(entity.getContent()));
71   -
72   - StringBuilder sb = new StringBuilder();
73   - String str;
74   - while ((str = br.readLine()) != null)
75   - sb.append(str);
76   -
77   - list = JSON.parseArray(JSON.parseObject(sb.toString()).getString("data"), GpsEntity.class);
78   - //过滤掉无效的点位
79   - list = GpsDataUtils.clearInvalid(list);
80   -
81   - List<GpsEntity> ups = new ArrayList<>();
82   - String nbbm;
83   - for (GpsEntity gps : list) {
84   - if (StringUtils.isBlank(gps.getDeviceId()))
85   - continue;
86   -
87   - if (gps_equals(gpsRealData.get(gps.getDeviceId()), gps))
88   - continue;
89   -
90   - nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId());
91   - gps.setNbbm(nbbm);
92   - ups.add(gps);
93   - }
94   - list = ups;
95   -
96   - if (null != response)
97   - response.close();
98   - }catch (Exception e){
99   - logger.error("", e);
100   - }
101   - return list;
102   - }
103   -
104   -
105   - private static boolean gps_equals(GpsEntity old, GpsEntity gps){
106   - if(old != null &&
107   - old.getTimestamp().equals(gps.getTimestamp()) &&
108   - old.getLat().equals(gps.getLat()) &&
109   - old.getLon().equals(gps.getLon()))
110   - return true;
111   - return false;
112   - }
113   -
114   - @Override
115   - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
116   - gpsRealData = applicationContext.getBean(GpsRealData.class);
117   - }
118   -}
  1 +package com.bsth.data.gpsdata_v2.load;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.bsth.data.BasicData;
  5 +import com.bsth.data.gpsdata_v2.GpsRealData;
  6 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  7 +import com.bsth.data.gpsdata_v2.utils.GpsDataUtils;
  8 +import com.bsth.util.ConfigUtil;
  9 +import org.apache.commons.lang3.StringUtils;
  10 +import org.apache.http.HttpEntity;
  11 +import org.apache.http.client.config.RequestConfig;
  12 +import org.apache.http.client.methods.CloseableHttpResponse;
  13 +import org.apache.http.client.methods.HttpGet;
  14 +import org.apache.http.impl.client.CloseableHttpClient;
  15 +import org.apache.http.impl.client.HttpClients;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
  18 +import org.springframework.beans.BeansException;
  19 +import org.springframework.context.ApplicationContext;
  20 +import org.springframework.context.ApplicationContextAware;
  21 +import org.springframework.stereotype.Component;
  22 +
  23 +import java.io.BufferedReader;
  24 +import java.io.InputStreamReader;
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +
  28 +/**
  29 + * 从网关http 接口加载数据
  30 + * Created by panzhao on 2017/11/15.
  31 + */
  32 +@Component
  33 +public class GatewayHttpLoader implements ApplicationContextAware{
  34 +
  35 + static Logger logger = LoggerFactory.getLogger(GatewayHttpLoader.class);
  36 +
  37 + static String url;
  38 + static List<GpsEntity> list;
  39 + static CloseableHttpClient httpClient = null;
  40 + static HttpGet get;
  41 + static RequestConfig requestConfig;
  42 + static CloseableHttpResponse response;
  43 + static HttpEntity entity;
  44 + static BufferedReader br;
  45 +
  46 + static GpsRealData gpsRealData;
  47 +
  48 + static{
  49 + url = ConfigUtil.get("http.gps.real.url");
  50 + list = new ArrayList<>();
  51 + httpClient = HttpClients.createDefault();
  52 + get = new HttpGet(url);
  53 + requestConfig = RequestConfig.custom()
  54 + .setConnectTimeout(1500).setConnectionRequestTimeout(1000)
  55 + .setSocketTimeout(1500).build();
  56 + get.setConfig(requestConfig);
  57 + }
  58 +
  59 + public static List<GpsEntity> load(){
  60 + try{
  61 + if(list.size() > 0)
  62 + list.clear();
  63 +
  64 + response = httpClient.execute(get);
  65 + entity = response.getEntity();
  66 +
  67 + if(null == entity)
  68 + return list;
  69 +
  70 + br = new BufferedReader(new InputStreamReader(entity.getContent()));
  71 +
  72 + StringBuilder sb = new StringBuilder();
  73 + String str;
  74 + while ((str = br.readLine()) != null)
  75 + sb.append(str);
  76 +
  77 + list = JSON.parseArray(JSON.parseObject(sb.toString()).getString("data"), GpsEntity.class);
  78 + //过滤掉无效的点位
  79 + list = GpsDataUtils.clearInvalid(list);
  80 +
  81 + List<GpsEntity> ups = new ArrayList<>();
  82 + String nbbm;
  83 + for (GpsEntity gps : list) {
  84 + if (StringUtils.isBlank(gps.getDeviceId()))
  85 + continue;
  86 +
  87 + if (gps_equals(gpsRealData.get(gps.getDeviceId()), gps))
  88 + continue;
  89 +
  90 + nbbm = BasicData.deviceId2NbbmMap.get(gps.getDeviceId());
  91 + gps.setNbbm(nbbm);
  92 + ups.add(gps);
  93 + }
  94 + list = ups;
  95 +
  96 + if (null != response)
  97 + response.close();
  98 + }catch (Exception e){
  99 + logger.error("", e);
  100 + }
  101 + return list;
  102 + }
  103 +
  104 +
  105 + private static boolean gps_equals(GpsEntity old, GpsEntity gps){
  106 + if(old != null &&
  107 + old.getTimestamp().equals(gps.getTimestamp()) &&
  108 + old.getLat().equals(gps.getLat()) &&
  109 + old.getLon().equals(gps.getLon()))
  110 + return true;
  111 + return false;
  112 + }
  113 +
  114 + @Override
  115 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  116 + gpsRealData = applicationContext.getBean(GpsRealData.class);
  117 + }
  118 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/load/SocketClientLoader.java
1   -package com.bsth.data.gpsdata_v2.load;
2   -
3   -import com.alibaba.fastjson.JSON;
4   -import com.bsth.data.BasicData;
5   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
6   -import com.bsth.data.gpsdata_v2.utils.GpsDataUtils;
7   -import com.bsth.util.ConfigUtil;
8   -import org.apache.http.HttpEntity;
9   -import org.apache.http.client.config.RequestConfig;
10   -import org.apache.http.client.methods.CloseableHttpResponse;
11   -import org.apache.http.client.methods.HttpGet;
12   -import org.apache.http.impl.client.CloseableHttpClient;
13   -import org.apache.http.impl.client.HttpClients;
14   -import org.slf4j.Logger;
15   -import org.slf4j.LoggerFactory;
16   -import org.springframework.stereotype.Component;
17   -
18   -import java.io.BufferedReader;
19   -import java.io.InputStreamReader;
20   -import java.util.ArrayList;
21   -import java.util.List;
22   -
23   -/**
24   - * 从专用的socket client 加载数据
25   - * Created by panzhao on 2017/11/15.
26   - */
27   -@Component
28   -public class SocketClientLoader {
29   -
30   - static Logger logger = LoggerFactory.getLogger(SocketClientLoader.class);
31   -
32   - static String url;
33   - static List<GpsEntity> list;
34   - static CloseableHttpClient httpClient = null;
35   - static HttpGet get;
36   - static RequestConfig requestConfig;
37   - static CloseableHttpResponse response;
38   - static HttpEntity entity;
39   - static BufferedReader br;
40   -
41   - static {
42   - url = ConfigUtil.get("http.gps.real.cache.url");
43   - list = new ArrayList<>();
44   - httpClient = HttpClients.createDefault();
45   - get = new HttpGet(url);
46   - requestConfig = RequestConfig.custom()
47   - .setConnectTimeout(1500).setConnectionRequestTimeout(1000)
48   - .setSocketTimeout(1500).build();
49   - get.setConfig(requestConfig);
50   - }
51   -
52   - public static List<GpsEntity> load(){
53   - try {
54   - if(list.size() > 0)
55   - list.clear();
56   - logger.info("load start...");
57   - response = httpClient.execute(get);
58   - entity = response.getEntity();
59   - if(null == entity)
60   - return list;
61   -
62   - br = new BufferedReader(new InputStreamReader(entity.getContent()));
63   - StringBuilder sb = new StringBuilder();
64   - String str;
65   - while ((str = br.readLine()) != null)
66   - sb.append(str);
67   -
68   - list = JSON.parseArray(sb.toString(), GpsEntity.class);
69   -
70   - //过滤掉无效的点位
71   - list = GpsDataUtils.clearInvalid(list);
72   -
73   - logger.info("load end!");
74   - for (GpsEntity gps : list) {
75   - gps.setNbbm(BasicData.deviceId2NbbmMap.get(gps.getDeviceId()));
76   - }
77   -
78   - if (null != response)
79   - response.close();
80   - } catch (Exception e) {
81   - logger.error("", e);
82   - }
83   -
84   - return list;
85   - }
86   -}
  1 +package com.bsth.data.gpsdata_v2.load;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.bsth.data.BasicData;
  5 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  6 +import com.bsth.data.gpsdata_v2.utils.GpsDataUtils;
  7 +import com.bsth.util.ConfigUtil;
  8 +import org.apache.http.HttpEntity;
  9 +import org.apache.http.client.config.RequestConfig;
  10 +import org.apache.http.client.methods.CloseableHttpResponse;
  11 +import org.apache.http.client.methods.HttpGet;
  12 +import org.apache.http.impl.client.CloseableHttpClient;
  13 +import org.apache.http.impl.client.HttpClients;
  14 +import org.slf4j.Logger;
  15 +import org.slf4j.LoggerFactory;
  16 +import org.springframework.stereotype.Component;
  17 +
  18 +import java.io.BufferedReader;
  19 +import java.io.InputStreamReader;
  20 +import java.util.ArrayList;
  21 +import java.util.List;
  22 +
  23 +/**
  24 + * 从专用的socket client 加载数据
  25 + * Created by panzhao on 2017/11/15.
  26 + */
  27 +@Component
  28 +public class SocketClientLoader {
  29 +
  30 + static Logger logger = LoggerFactory.getLogger(SocketClientLoader.class);
  31 +
  32 + static String url;
  33 + static List<GpsEntity> list;
  34 + static CloseableHttpClient httpClient = null;
  35 + static HttpGet get;
  36 + static RequestConfig requestConfig;
  37 + static CloseableHttpResponse response;
  38 + static HttpEntity entity;
  39 + static BufferedReader br;
  40 +
  41 + static {
  42 + url = ConfigUtil.get("http.gps.real.cache.url");
  43 + list = new ArrayList<>();
  44 + httpClient = HttpClients.createDefault();
  45 + get = new HttpGet(url);
  46 + requestConfig = RequestConfig.custom()
  47 + .setConnectTimeout(1500).setConnectionRequestTimeout(1000)
  48 + .setSocketTimeout(1500).build();
  49 + get.setConfig(requestConfig);
  50 + }
  51 +
  52 + public static List<GpsEntity> load(){
  53 + try {
  54 + if(list.size() > 0)
  55 + list.clear();
  56 + logger.info("load start...");
  57 + response = httpClient.execute(get);
  58 + entity = response.getEntity();
  59 + if(null == entity)
  60 + return list;
  61 +
  62 + br = new BufferedReader(new InputStreamReader(entity.getContent()));
  63 + StringBuilder sb = new StringBuilder();
  64 + String str;
  65 + while ((str = br.readLine()) != null)
  66 + sb.append(str);
  67 +
  68 + list = JSON.parseArray(sb.toString(), GpsEntity.class);
  69 +
  70 + //过滤掉无效的点位
  71 + list = GpsDataUtils.clearInvalid(list);
  72 +
  73 + logger.info("load end!");
  74 + for (GpsEntity gps : list) {
  75 + gps.setNbbm(BasicData.deviceId2NbbmMap.get(gps.getDeviceId()));
  76 + }
  77 +
  78 + if (null != response)
  79 + response.close();
  80 + } catch (Exception e) {
  81 + logger.error("", e);
  82 + }
  83 +
  84 + return list;
  85 + }
  86 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/rfid/UploadRfidDataService.java
1 1 package com.bsth.data.gpsdata_v2.rfid;
2 2  
  3 +import com.alibaba.fastjson.JSON;
3 4 import com.bsth.data.gpsdata_v2.rfid.entity.RfidInoutStation;
4 5 import com.bsth.data.gpsdata_v2.rfid.handle.RfidSignalHandle;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
5 8 import org.springframework.beans.factory.annotation.Autowired;
6 9 import org.springframework.web.bind.annotation.RequestBody;
7 10 import org.springframework.web.bind.annotation.RequestMapping;
... ... @@ -20,8 +23,11 @@ public class UploadRfidDataService {
20 23 @Autowired
21 24 RfidSignalHandle rfidSignalHandle;
22 25  
  26 + Logger logger = LoggerFactory.getLogger(this.getClass());
  27 +
23 28 @RequestMapping("inside")
24 29 public void inside(@RequestBody List<RfidInoutStation> list) {
  30 + logger.info("up rfid: " + JSON.toJSONString(list));
25 31 rfidSignalHandle.handle(list);
26 32 }
27 33 -}
  34 +}
28 35 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/rfid/entity/RfidInoutStation.java
1   -package com.bsth.data.gpsdata_v2.rfid.entity;
2   -
3   -/**
4   - * RFID 进出数据
5   - * Created by panzhao on 2017/11/22.
6   - */
7   -public class RfidInoutStation {
8   -
9   - private String nbbm;
10   -
11   - private String station;
12   -
13   - /**
14   - * 0 进
15   - * 1 出
16   - */
17   - private int type;
18   -
19   - /**
20   - * 信号时间
21   - */
22   - private long t;
23   -
24   - public String getNbbm() {
25   - return nbbm;
26   - }
27   -
28   - public void setNbbm(String nbbm) {
29   - this.nbbm = nbbm;
30   - }
31   -
32   - public String getStation() {
33   - return station;
34   - }
35   -
36   - public void setStation(String station) {
37   - this.station = station;
38   - }
39   -
40   - public int getType() {
41   - return type;
42   - }
43   -
44   - public void setType(int type) {
45   - this.type = type;
46   - }
47   -
48   - public long getT() {
49   - return t;
50   - }
51   -
52   - public void setT(long t) {
53   - this.t = t;
54   - }
55   -}
  1 +package com.bsth.data.gpsdata_v2.rfid.entity;
  2 +
  3 +/**
  4 + * RFID 进出数据
  5 + * Created by panzhao on 2017/11/22.
  6 + */
  7 +public class RfidInoutStation {
  8 +
  9 + private String nbbm;
  10 +
  11 + private String station;
  12 +
  13 + /**
  14 + * 0 进
  15 + * 1 出
  16 + */
  17 + private int type;
  18 +
  19 + /**
  20 + * 信号时间
  21 + */
  22 + private long t;
  23 +
  24 + public String getNbbm() {
  25 + return nbbm;
  26 + }
  27 +
  28 + public void setNbbm(String nbbm) {
  29 + this.nbbm = nbbm;
  30 + }
  31 +
  32 + public String getStation() {
  33 + return station;
  34 + }
  35 +
  36 + public void setStation(String station) {
  37 + this.station = station;
  38 + }
  39 +
  40 + public int getType() {
  41 + return type;
  42 + }
  43 +
  44 + public void setType(int type) {
  45 + this.type = type;
  46 + }
  47 +
  48 + public long getT() {
  49 + return t;
  50 + }
  51 +
  52 + public void setT(long t) {
  53 + this.t = t;
  54 + }
  55 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/rfid/handle/RfidSignalHandle.java
... ... @@ -30,6 +30,8 @@ public class RfidSignalHandle {
30 30 @Autowired
31 31 GpsStatusManager gpsStatusManager;
32 32  
  33 + private final static int MAX_TIME_DIFF = 1000 * 60 * 60 * 2;
  34 +
33 35 Logger logger = LoggerFactory.getLogger(this.getClass());
34 36  
35 37 public void handle(List<RfidInoutStation> list){
... ... @@ -53,6 +55,10 @@ public class RfidSignalHandle {
53 55 if(null == sch)
54 56 return;
55 57  
  58 + //最大时间差
  59 + if(Math.abs(sch.getDfsjT() - signal.getT()) > MAX_TIME_DIFF)
  60 + return;
  61 +
56 62 if(sch.getQdzCode().equals(signal.getStation())
57 63 && StringUtils.isEmpty(sch.getFcsjActual())){
58 64  
... ... @@ -81,12 +87,18 @@ public class RfidSignalHandle {
81 87 String nbbm = signal.getNbbm();
82 88 ScheduleRealInfo sch = dayOfSchedule.executeCurr(nbbm);
83 89  
  90 + if(null == sch)
  91 + return;
  92 +
  93 + //最大时间差
  94 + if(Math.abs(sch.getDfsjT() - signal.getT()) > MAX_TIME_DIFF)
  95 + return;
  96 +
84 97 if(sch.getZdzCode().equals(signal.getStation())
85 98 && StringUtils.isEmpty(sch.getZdsjActual())){
86 99  
87 100 sch.setZdsjActualAll(signal.getT());
88 101  
89   -
90 102 //持久化
91 103 dayOfSchedule.save(sch);
92 104  
... ... @@ -137,4 +149,4 @@ public class RfidSignalHandle {
137 149 private void nonService(ScheduleRealInfo sch, String sender){
138 150 gpsStatusManager.changeServiceState(sch.getClZbh(), sch.getXlDir(), 1, sender);
139 151 }
140 152 -}
  153 +}
141 154 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/status_manager/GpsStatusManager.java
1   -package com.bsth.data.gpsdata_v2.status_manager;
2   -
3   -import com.bsth.Application;
4   -import com.bsth.data.gpsdata_v2.status_manager.gps_line_state.LineStateHandle;
5   -import com.bsth.data.gpsdata_v2.status_manager.gps_service_state.ServiceStateHandle;
6   -import org.springframework.beans.factory.annotation.Autowired;
7   -import org.springframework.boot.CommandLineRunner;
8   -import org.springframework.stereotype.Component;
9   -
10   -import java.util.concurrent.TimeUnit;
11   -
12   -/**
13   - * GPS 状态管理
14   - * Created by panzhao on 2017/7/13.
15   - */
16   -@Component
17   -public class GpsStatusManager implements CommandLineRunner {
18   -
19   - @Autowired
20   - StatusCheckThread checkThread;
21   -
22   - @Autowired
23   - LineStateHandle lineStateHandle;
24   -
25   - @Autowired
26   - ServiceStateHandle serviceStateHandle;
27   -
28   - /**
29   - * 切换线路
30   - * @param nbbm
31   - * @param lineCode
32   - * @param sender
33   - */
34   - public void changeLine(String nbbm, String lineCode, String sender){
35   - lineStateHandle.changeLine(nbbm, lineCode, sender);
36   - }
37   -
38   - /**
39   - * 切换营运状态
40   - * @param nbbm
41   - * @param state 0 营运, 1:非营运
42   - * @param sender
43   - */
44   - public void changeServiceState(String nbbm, String upDown,int state, String sender){
45   - changeServiceState(nbbm, Integer.parseInt(upDown), state, sender);
46   - }
47   -
48   - /**
49   - * 切换营运状态
50   - * @param nbbm
51   - * @param state 0 营运, 1:非营运
52   - * @param sender
53   - */
54   - public void changeServiceState(String nbbm, int upDown,int state, String sender){
55   - serviceStateHandle.changeState(nbbm, upDown, state, sender);
56   - }
57   -
58   - @Override
59   - public void run(String... strings) throws Exception {
60   - Application.mainServices.scheduleWithFixedDelay(checkThread, 120, 120, TimeUnit.SECONDS);
61   - }
62   -
63   - @Component
64   - public static class StatusCheckThread extends Thread{
65   -
66   - @Autowired
67   - LineStateHandle lineStateHandle;
68   -
69   - @Autowired
70   - ServiceStateHandle serviceStateHandle;
71   -
72   - @Override
73   - public void run() {
74   - /** 检查线路切换结果 */
75   - lineStateHandle.checkResultAll();
76   - /** 检查营运状态切换结果 */
77   - serviceStateHandle.checkResultAll();
78   - }
79   - }
80   -}
  1 +package com.bsth.data.gpsdata_v2.status_manager;
  2 +
  3 +import com.bsth.Application;
  4 +import com.bsth.data.gpsdata_v2.status_manager.gps_line_state.LineStateHandle;
  5 +import com.bsth.data.gpsdata_v2.status_manager.gps_service_state.ServiceStateHandle;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.boot.CommandLineRunner;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import java.util.concurrent.TimeUnit;
  11 +
  12 +/**
  13 + * GPS 状态管理
  14 + * Created by panzhao on 2017/7/13.
  15 + */
  16 +@Component
  17 +public class GpsStatusManager implements CommandLineRunner {
  18 +
  19 + @Autowired
  20 + StatusCheckThread checkThread;
  21 +
  22 + @Autowired
  23 + LineStateHandle lineStateHandle;
  24 +
  25 + @Autowired
  26 + ServiceStateHandle serviceStateHandle;
  27 +
  28 + /**
  29 + * 切换线路
  30 + * @param nbbm
  31 + * @param lineCode
  32 + * @param sender
  33 + */
  34 + public void changeLine(String nbbm, String lineCode, String sender){
  35 + lineStateHandle.changeLine(nbbm, lineCode, sender);
  36 + }
  37 +
  38 + /**
  39 + * 切换营运状态
  40 + * @param nbbm
  41 + * @param state 0 营运, 1:非营运
  42 + * @param sender
  43 + */
  44 + public void changeServiceState(String nbbm, String upDown,int state, String sender){
  45 + changeServiceState(nbbm, Integer.parseInt(upDown), state, sender);
  46 + }
  47 +
  48 + /**
  49 + * 切换营运状态
  50 + * @param nbbm
  51 + * @param state 0 营运, 1:非营运
  52 + * @param sender
  53 + */
  54 + public void changeServiceState(String nbbm, int upDown,int state, String sender){
  55 + serviceStateHandle.changeState(nbbm, upDown, state, sender);
  56 + }
  57 +
  58 + @Override
  59 + public void run(String... strings) throws Exception {
  60 + Application.mainServices.scheduleWithFixedDelay(checkThread, 120, 120, TimeUnit.SECONDS);
  61 + }
  62 +
  63 + @Component
  64 + public static class StatusCheckThread extends Thread{
  65 +
  66 + @Autowired
  67 + LineStateHandle lineStateHandle;
  68 +
  69 + @Autowired
  70 + ServiceStateHandle serviceStateHandle;
  71 +
  72 + @Override
  73 + public void run() {
  74 + /** 检查线路切换结果 */
  75 + lineStateHandle.checkResultAll();
  76 + /** 检查营运状态切换结果 */
  77 + serviceStateHandle.checkResultAll();
  78 + }
  79 + }
  80 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/status_manager/gps_line_state/ChangeBean.java
1   -package com.bsth.data.gpsdata_v2.status_manager.gps_line_state;
2   -
3   -/**
4   - * Created by panzhao on 2017/7/13.
5   - */
6   -public class ChangeBean {
7   -
8   - /**
9   - * 车辆自编号
10   - */
11   - private String nbbm;
12   -
13   - /**
14   - * 要切换到的线路
15   - */
16   - private String lineCode;
17   -
18   - /**
19   - * 指令发送次数
20   - */
21   - private int sendCount;
22   -
23   - /**
24   - * 上次指令时间
25   - */
26   - private long st;
27   -
28   - /**发送人 */
29   - private String sender;
30   -
31   - public static ChangeBean getInstance(String nbbm, String lineCode, String sender){
32   - ChangeBean cb = new ChangeBean();
33   - cb.setNbbm(nbbm);
34   - cb.setLineCode(lineCode);
35   - cb.setSendCount(0);
36   - cb.setSender(sender);
37   - return cb;
38   - }
39   -
40   - public void countPlus(){
41   - sendCount ++;
42   - }
43   -
44   - public String getLineCode() {
45   - return lineCode;
46   - }
47   -
48   - public void setLineCode(String lineCode) {
49   - this.lineCode = lineCode;
50   - }
51   -
52   - public int getSendCount() {
53   - return sendCount;
54   - }
55   -
56   - public void setSendCount(int sendCount) {
57   - this.sendCount = sendCount;
58   - }
59   -
60   - public long getSt() {
61   - return st;
62   - }
63   -
64   - public void setSt(long st) {
65   - this.st = st;
66   - }
67   -
68   - public String getSender() {
69   - return sender;
70   - }
71   -
72   - public void setSender(String sender) {
73   - this.sender = sender;
74   - }
75   -
76   - public String getNbbm() {
77   - return nbbm;
78   - }
79   -
80   - public void setNbbm(String nbbm) {
81   - this.nbbm = nbbm;
82   - }
83   -}
  1 +package com.bsth.data.gpsdata_v2.status_manager.gps_line_state;
  2 +
  3 +/**
  4 + * Created by panzhao on 2017/7/13.
  5 + */
  6 +public class ChangeBean {
  7 +
  8 + /**
  9 + * 车辆自编号
  10 + */
  11 + private String nbbm;
  12 +
  13 + /**
  14 + * 要切换到的线路
  15 + */
  16 + private String lineCode;
  17 +
  18 + /**
  19 + * 指令发送次数
  20 + */
  21 + private int sendCount;
  22 +
  23 + /**
  24 + * 上次指令时间
  25 + */
  26 + private long st;
  27 +
  28 + /**发送人 */
  29 + private String sender;
  30 +
  31 + public static ChangeBean getInstance(String nbbm, String lineCode, String sender){
  32 + ChangeBean cb = new ChangeBean();
  33 + cb.setNbbm(nbbm);
  34 + cb.setLineCode(lineCode);
  35 + cb.setSendCount(0);
  36 + cb.setSender(sender);
  37 + return cb;
  38 + }
  39 +
  40 + public void countPlus(){
  41 + sendCount ++;
  42 + }
  43 +
  44 + public String getLineCode() {
  45 + return lineCode;
  46 + }
  47 +
  48 + public void setLineCode(String lineCode) {
  49 + this.lineCode = lineCode;
  50 + }
  51 +
  52 + public int getSendCount() {
  53 + return sendCount;
  54 + }
  55 +
  56 + public void setSendCount(int sendCount) {
  57 + this.sendCount = sendCount;
  58 + }
  59 +
  60 + public long getSt() {
  61 + return st;
  62 + }
  63 +
  64 + public void setSt(long st) {
  65 + this.st = st;
  66 + }
  67 +
  68 + public String getSender() {
  69 + return sender;
  70 + }
  71 +
  72 + public void setSender(String sender) {
  73 + this.sender = sender;
  74 + }
  75 +
  76 + public String getNbbm() {
  77 + return nbbm;
  78 + }
  79 +
  80 + public void setNbbm(String nbbm) {
  81 + this.nbbm = nbbm;
  82 + }
  83 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/status_manager/gps_line_state/LineStateHandle.java
1   -package com.bsth.data.gpsdata_v2.status_manager.gps_line_state;
2   -
3   -import com.bsth.data.gpsdata_v2.GpsRealData;
4   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
5   -import com.bsth.data.msg_queue.DirectivePushQueue;
6   -import com.bsth.service.directive.DirectiveService;
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
9   -import org.springframework.beans.factory.annotation.Autowired;
10   -import org.springframework.stereotype.Component;
11   -
12   -import java.util.Collection;
13   -import java.util.concurrent.ConcurrentHashMap;
14   -
15   -/**
16   - * 设备线路状态处理
17   - * Created by panzhao on 2017/7/13.
18   - */
19   -@Component
20   -public class LineStateHandle {
21   -
22   - private static ConcurrentHashMap<String, ChangeBean> map;
23   -
24   - @Autowired
25   - DirectiveService directiveService;
26   - @Autowired
27   - GpsRealData gpsRealData;
28   -
29   - Logger logger = LoggerFactory.getLogger(this.getClass());
30   -
31   - /** 重发次数 */
32   - private final static int MAX_SEND_COUNT=3;
33   - /** 重发间隔 */
34   - private final static int SEND_SPACE=1000 * 60 * 6;
35   - /** 最大有效时间 */
36   - private final static int MAX_AVAIL_TIME=1000 * 60 * 60 * 2;
37   -
38   - static{
39   - map = new ConcurrentHashMap();
40   - }
41   -
42   - public void changeLine(String nbbm, String lineCode, String sender){
43   - ChangeBean cb = map.get(nbbm);
44   - if(cb != null && cb.getLineCode().equals(lineCode)){
45   - return;
46   - }
47   -
48   - cb = ChangeBean.getInstance(nbbm, lineCode, sender);
49   - map.put(nbbm, cb);
50   -
51   - changeLine(cb);
52   - }
53   -
54   - private void changeLine(ChangeBean cb){
55   - cb.setSt(System.currentTimeMillis());
56   - cb.countPlus();
57   - DirectivePushQueue.put64(cb.getNbbm(), cb.getLineCode(), cb.getSender());
58   - }
59   -
60   -
61   - public void checkResultAll(){
62   - Collection<ChangeBean> cbs = map.values();
63   - for(ChangeBean cb : cbs){
64   - checkResult(cb);
65   - }
66   - }
67   -
68   - private void checkResult(ChangeBean cb){
69   - try{
70   - GpsEntity gps = gpsRealData.getByNbbm(cb.getNbbm());
71   - if(gps == null)
72   - return;
73   -
74   - if(cb.getLineCode().equals(gps.getLineId())){
75   - map.remove(cb.getNbbm());
76   - logger.info("线路切换成功," + cb.getNbbm() + "、" + cb.getLineCode());
77   - }
78   - else{
79   - reSend(cb);
80   - }
81   - }catch (Exception e){
82   - logger.error("", e);
83   - }
84   - }
85   -
86   - private void reSend(ChangeBean cb){
87   - if(cb.getSendCount() >= MAX_SEND_COUNT){
88   - map.remove(cb.getNbbm());
89   - logger.info("超过重发次数," + cb.getNbbm() + "、" + cb.getLineCode());
90   - return;
91   - }
92   -
93   - long diff = System.currentTimeMillis() - cb.getSt();
94   - if(diff >= MAX_AVAIL_TIME){
95   - map.remove(cb.getNbbm());
96   - logger.info("超过有效时间," + cb.getNbbm() + "、" + cb.getLineCode() + "、" + cb.getSt());
97   - return;
98   - }
99   -
100   - if(diff >= SEND_SPACE){
101   - cb.setSender("补发@系统");
102   - changeLine(cb);
103   - logger.info("重发线路切换指令," + cb.getNbbm() + "、" + cb.getLineCode());
104   - return;
105   - }
106   - }
107   -}
  1 +package com.bsth.data.gpsdata_v2.status_manager.gps_line_state;
  2 +
  3 +import com.bsth.data.gpsdata_v2.GpsRealData;
  4 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  5 +import com.bsth.data.msg_queue.DirectivePushQueue;
  6 +import com.bsth.service.directive.DirectiveService;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.Collection;
  13 +import java.util.concurrent.ConcurrentHashMap;
  14 +
  15 +/**
  16 + * 设备线路状态处理
  17 + * Created by panzhao on 2017/7/13.
  18 + */
  19 +@Component
  20 +public class LineStateHandle {
  21 +
  22 + private static ConcurrentHashMap<String, ChangeBean> map;
  23 +
  24 + @Autowired
  25 + DirectiveService directiveService;
  26 + @Autowired
  27 + GpsRealData gpsRealData;
  28 +
  29 + Logger logger = LoggerFactory.getLogger(this.getClass());
  30 +
  31 + /** 重发次数 */
  32 + private final static int MAX_SEND_COUNT=3;
  33 + /** 重发间隔 */
  34 + private final static int SEND_SPACE=1000 * 60 * 6;
  35 + /** 最大有效时间 */
  36 + private final static int MAX_AVAIL_TIME=1000 * 60 * 60 * 2;
  37 +
  38 + static{
  39 + map = new ConcurrentHashMap();
  40 + }
  41 +
  42 + public void changeLine(String nbbm, String lineCode, String sender){
  43 + ChangeBean cb = map.get(nbbm);
  44 + if(cb != null && cb.getLineCode().equals(lineCode)){
  45 + return;
  46 + }
  47 +
  48 + cb = ChangeBean.getInstance(nbbm, lineCode, sender);
  49 + map.put(nbbm, cb);
  50 +
  51 + changeLine(cb);
  52 + }
  53 +
  54 + private void changeLine(ChangeBean cb){
  55 + cb.setSt(System.currentTimeMillis());
  56 + cb.countPlus();
  57 + DirectivePushQueue.put64(cb.getNbbm(), cb.getLineCode(), cb.getSender());
  58 + }
  59 +
  60 +
  61 + public void checkResultAll(){
  62 + Collection<ChangeBean> cbs = map.values();
  63 + for(ChangeBean cb : cbs){
  64 + checkResult(cb);
  65 + }
  66 + }
  67 +
  68 + private void checkResult(ChangeBean cb){
  69 + try{
  70 + GpsEntity gps = gpsRealData.getByNbbm(cb.getNbbm());
  71 + if(gps == null)
  72 + return;
  73 +
  74 + if(cb.getLineCode().equals(gps.getLineId())){
  75 + map.remove(cb.getNbbm());
  76 + logger.info("线路切换成功," + cb.getNbbm() + "、" + cb.getLineCode());
  77 + }
  78 + else{
  79 + reSend(cb);
  80 + }
  81 + }catch (Exception e){
  82 + logger.error("", e);
  83 + }
  84 + }
  85 +
  86 + private void reSend(ChangeBean cb){
  87 + if(cb.getSendCount() >= MAX_SEND_COUNT){
  88 + map.remove(cb.getNbbm());
  89 + logger.info("超过重发次数," + cb.getNbbm() + "、" + cb.getLineCode());
  90 + return;
  91 + }
  92 +
  93 + long diff = System.currentTimeMillis() - cb.getSt();
  94 + if(diff >= MAX_AVAIL_TIME){
  95 + map.remove(cb.getNbbm());
  96 + logger.info("超过有效时间," + cb.getNbbm() + "、" + cb.getLineCode() + "、" + cb.getSt());
  97 + return;
  98 + }
  99 +
  100 + if(diff >= SEND_SPACE){
  101 + cb.setSender("补发@系统");
  102 + changeLine(cb);
  103 + logger.info("重发线路切换指令," + cb.getNbbm() + "、" + cb.getLineCode());
  104 + return;
  105 + }
  106 + }
  107 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/status_manager/gps_service_state/ServiceStateHandle.java
1   -package com.bsth.data.gpsdata_v2.status_manager.gps_service_state;
2   -
3   -import com.bsth.data.gpsdata_v2.GpsRealData;
4   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
5   -import com.bsth.data.msg_queue.DirectivePushQueue;
6   -import com.bsth.service.directive.DirectiveService;
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
9   -import org.springframework.beans.factory.annotation.Autowired;
10   -import org.springframework.stereotype.Component;
11   -
12   -import java.util.Collection;
13   -import java.util.concurrent.ConcurrentHashMap;
14   -
15   -/**
16   - * 设备营运状态/上下行 处理
17   - * Created by panzhao on 2017/7/13.
18   - */
19   -@Component
20   -public class ServiceStateHandle {
21   -
22   - private static ConcurrentHashMap<String, StateBean> map;
23   -
24   - @Autowired
25   - DirectiveService directiveService;
26   - @Autowired
27   - GpsRealData gpsRealData;
28   -
29   - Logger logger = LoggerFactory.getLogger(this.getClass());
30   -
31   - /** 重发次数 */
32   - private final static int MAX_SEND_COUNT=3;
33   - /** 重发间隔 */
34   - private final static int SEND_SPACE=1000 * 60 * 3;
35   - /** 最大有效时间 */
36   - private final static int MAX_AVAIL_TIME=1000 * 60 * 50;
37   -
38   - static{
39   - map = new ConcurrentHashMap();
40   - }
41   -
42   - public void changeState(String nbbm, int upDown ,int state, String sender){
43   - if(map.containsKey(nbbm)){
44   - return;
45   - }
46   - StateBean sb = StateBean.getInstance(nbbm, upDown, state, sender);
47   - map.put(nbbm, sb);
48   - changeState(sb);
49   - }
50   -
51   - private void changeState(StateBean sb){
52   - sb.setSt(System.currentTimeMillis());
53   - sb.countPlus();
54   - DirectivePushQueue.put6003(sb.getNbbm(), sb.getState(), sb.getUpDown(), sb.getSender());
55   - }
56   -
57   - public void checkResultAll(){
58   - Collection<StateBean> sbs = map.values();
59   - for(StateBean sb : sbs){
60   - checkResult(sb);
61   - }
62   - }
63   -
64   - private void checkResult(StateBean sb){
65   - try{
66   - GpsEntity gps = gpsRealData.getByNbbm(sb.getNbbm());
67   - if(gps == null)
68   - return;
69   -
70   - if(gps.getState().equals(sb.getState()) && gps.getUpDown() == sb.getUpDown()){
71   - map.remove(sb.getNbbm());
72   - logger.info("状态切换成功," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getUpDown());
73   - }
74   - else
75   - reSend(sb);
76   - }catch (Exception e){
77   - logger.error("", e);
78   - }
79   - }
80   -
81   - private void reSend(StateBean sb){
82   - if(sb.getSendCount() >= MAX_SEND_COUNT){
83   - map.remove(sb.getNbbm());
84   - logger.info("超过重发次数," + sb.getNbbm() + "、" + sb.getState());
85   - return;
86   - }
87   -
88   - long diff = System.currentTimeMillis() - sb.getSt();
89   - if(diff >= MAX_AVAIL_TIME){
90   - map.remove(sb.getNbbm());
91   - logger.info("状态切换超过有效时间," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getSt());
92   - return;
93   - }
94   -
95   - if(diff >= SEND_SPACE){
96   - sb.setSender("补发@系统");
97   - changeState(sb);
98   - logger.info("重发状态切换指令," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getUpDown());
99   - return;
100   - }
101   - }
102   -}
  1 +package com.bsth.data.gpsdata_v2.status_manager.gps_service_state;
  2 +
  3 +import com.bsth.data.gpsdata_v2.GpsRealData;
  4 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  5 +import com.bsth.data.msg_queue.DirectivePushQueue;
  6 +import com.bsth.service.directive.DirectiveService;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.Collection;
  13 +import java.util.concurrent.ConcurrentHashMap;
  14 +
  15 +/**
  16 + * 设备营运状态/上下行 处理
  17 + * Created by panzhao on 2017/7/13.
  18 + */
  19 +@Component
  20 +public class ServiceStateHandle {
  21 +
  22 + private static ConcurrentHashMap<String, StateBean> map;
  23 +
  24 + @Autowired
  25 + DirectiveService directiveService;
  26 + @Autowired
  27 + GpsRealData gpsRealData;
  28 +
  29 + Logger logger = LoggerFactory.getLogger(this.getClass());
  30 +
  31 + /** 重发次数 */
  32 + private final static int MAX_SEND_COUNT=3;
  33 + /** 重发间隔 */
  34 + private final static int SEND_SPACE=1000 * 60 * 3;
  35 + /** 最大有效时间 */
  36 + private final static int MAX_AVAIL_TIME=1000 * 60 * 50;
  37 +
  38 + static{
  39 + map = new ConcurrentHashMap();
  40 + }
  41 +
  42 + public void changeState(String nbbm, int upDown ,int state, String sender){
  43 + if(map.containsKey(nbbm)){
  44 + return;
  45 + }
  46 + StateBean sb = StateBean.getInstance(nbbm, upDown, state, sender);
  47 + map.put(nbbm, sb);
  48 + changeState(sb);
  49 + }
  50 +
  51 + private void changeState(StateBean sb){
  52 + sb.setSt(System.currentTimeMillis());
  53 + sb.countPlus();
  54 + DirectivePushQueue.put6003(sb.getNbbm(), sb.getState(), sb.getUpDown(), sb.getSender());
  55 + }
  56 +
  57 + public void checkResultAll(){
  58 + Collection<StateBean> sbs = map.values();
  59 + for(StateBean sb : sbs){
  60 + checkResult(sb);
  61 + }
  62 + }
  63 +
  64 + private void checkResult(StateBean sb){
  65 + try{
  66 + GpsEntity gps = gpsRealData.getByNbbm(sb.getNbbm());
  67 + if(gps == null)
  68 + return;
  69 +
  70 + if(gps.getState().equals(sb.getState()) && gps.getUpDown() == sb.getUpDown()){
  71 + map.remove(sb.getNbbm());
  72 + logger.info("状态切换成功," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getUpDown());
  73 + }
  74 + else
  75 + reSend(sb);
  76 + }catch (Exception e){
  77 + logger.error("", e);
  78 + }
  79 + }
  80 +
  81 + private void reSend(StateBean sb){
  82 + if(sb.getSendCount() >= MAX_SEND_COUNT){
  83 + map.remove(sb.getNbbm());
  84 + logger.info("超过重发次数," + sb.getNbbm() + "、" + sb.getState());
  85 + return;
  86 + }
  87 +
  88 + long diff = System.currentTimeMillis() - sb.getSt();
  89 + if(diff >= MAX_AVAIL_TIME){
  90 + map.remove(sb.getNbbm());
  91 + logger.info("状态切换超过有效时间," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getSt());
  92 + return;
  93 + }
  94 +
  95 + if(diff >= SEND_SPACE){
  96 + sb.setSender("补发@系统");
  97 + changeState(sb);
  98 + logger.info("重发状态切换指令," + sb.getNbbm() + "、" + sb.getState() + "、" + sb.getUpDown());
  99 + return;
  100 + }
  101 + }
  102 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/status_manager/gps_service_state/StateBean.java
1   -package com.bsth.data.gpsdata_v2.status_manager.gps_service_state;
2   -
3   -/**
4   - * Created by panzhao on 2017/7/13.
5   - */
6   -public class StateBean {
7   -
8   - /**
9   - * 车辆自编号
10   - */
11   - private String nbbm;
12   -
13   - /**
14   - * 要切换到营运状态
15   - */
16   - private int state;
17   -
18   - /**
19   - * 要切换到的上下行
20   - */
21   - private int upDown;
22   -
23   - /**
24   - * 指令发送次数
25   - */
26   - private int sendCount;
27   -
28   - /**
29   - * 上次指令时间
30   - */
31   - private long st;
32   -
33   - /**发送人 */
34   - private String sender;
35   -
36   - public static StateBean getInstance(String nbbm, int upDown, int state, String sender){
37   - StateBean sb = new StateBean();
38   - sb.setNbbm(nbbm);
39   - sb.setState(state);
40   - sb.setSendCount(0);
41   - sb.setSender(sender);
42   - sb.setUpDown(upDown);
43   - return sb;
44   - }
45   -
46   - public int getState() {
47   - return state;
48   - }
49   -
50   - public void setState(int state) {
51   - this.state = state;
52   - }
53   -
54   - public int getSendCount() {
55   - return sendCount;
56   - }
57   -
58   - public void setSendCount(int sendCount) {
59   - this.sendCount = sendCount;
60   - }
61   -
62   - public long getSt() {
63   - return st;
64   - }
65   -
66   - public void setSt(long st) {
67   - this.st = st;
68   - }
69   -
70   - public String getSender() {
71   - return sender;
72   - }
73   -
74   - public void setSender(String sender) {
75   - this.sender = sender;
76   - }
77   -
78   - public void countPlus(){
79   - sendCount ++;
80   - }
81   -
82   - public int getUpDown() {
83   - return upDown;
84   - }
85   -
86   - public void setUpDown(int upDown) {
87   - this.upDown = upDown;
88   - }
89   -
90   - public String getNbbm() {
91   - return nbbm;
92   - }
93   -
94   - public void setNbbm(String nbbm) {
95   - this.nbbm = nbbm;
96   - }
97   -}
  1 +package com.bsth.data.gpsdata_v2.status_manager.gps_service_state;
  2 +
  3 +/**
  4 + * Created by panzhao on 2017/7/13.
  5 + */
  6 +public class StateBean {
  7 +
  8 + /**
  9 + * 车辆自编号
  10 + */
  11 + private String nbbm;
  12 +
  13 + /**
  14 + * 要切换到营运状态
  15 + */
  16 + private int state;
  17 +
  18 + /**
  19 + * 要切换到的上下行
  20 + */
  21 + private int upDown;
  22 +
  23 + /**
  24 + * 指令发送次数
  25 + */
  26 + private int sendCount;
  27 +
  28 + /**
  29 + * 上次指令时间
  30 + */
  31 + private long st;
  32 +
  33 + /**发送人 */
  34 + private String sender;
  35 +
  36 + public static StateBean getInstance(String nbbm, int upDown, int state, String sender){
  37 + StateBean sb = new StateBean();
  38 + sb.setNbbm(nbbm);
  39 + sb.setState(state);
  40 + sb.setSendCount(0);
  41 + sb.setSender(sender);
  42 + sb.setUpDown(upDown);
  43 + return sb;
  44 + }
  45 +
  46 + public int getState() {
  47 + return state;
  48 + }
  49 +
  50 + public void setState(int state) {
  51 + this.state = state;
  52 + }
  53 +
  54 + public int getSendCount() {
  55 + return sendCount;
  56 + }
  57 +
  58 + public void setSendCount(int sendCount) {
  59 + this.sendCount = sendCount;
  60 + }
  61 +
  62 + public long getSt() {
  63 + return st;
  64 + }
  65 +
  66 + public void setSt(long st) {
  67 + this.st = st;
  68 + }
  69 +
  70 + public String getSender() {
  71 + return sender;
  72 + }
  73 +
  74 + public void setSender(String sender) {
  75 + this.sender = sender;
  76 + }
  77 +
  78 + public void countPlus(){
  79 + sendCount ++;
  80 + }
  81 +
  82 + public int getUpDown() {
  83 + return upDown;
  84 + }
  85 +
  86 + public void setUpDown(int upDown) {
  87 + this.upDown = upDown;
  88 + }
  89 +
  90 + public String getNbbm() {
  91 + return nbbm;
  92 + }
  93 +
  94 + public void setNbbm(String nbbm) {
  95 + this.nbbm = nbbm;
  96 + }
  97 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/thread/GpsDataLoaderThread.java
1   -package com.bsth.data.gpsdata_v2.thread;
2   -
3   -import com.bsth.data.gpsdata_v2.DataHandleProcess;
4   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
5   -import com.bsth.data.gpsdata_v2.load.GatewayHttpLoader;
6   -import com.bsth.data.gpsdata_v2.load.SocketClientLoader;
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
9   -import org.springframework.beans.factory.annotation.Autowired;
10   -import org.springframework.stereotype.Component;
11   -
12   -import java.util.List;
13   -
14   -/**
15   - * Created by panzhao on 2017/1/11.
16   - */
17   -@Component
18   -public class GpsDataLoaderThread extends Thread {
19   -
20   - Logger logger = LoggerFactory.getLogger(this.getClass());
21   -
22   - //0:从GPS客户端内存获取 -1:从网关获取
23   - private static int flag = 0;
24   -
25   - public static void setFlag(int v) {
26   - flag = v;
27   - }
28   -
29   - @Autowired
30   - DataHandleProcess handleProcess;
31   -
32   - @Override
33   - public void run() {
34   - try {
35   - List<GpsEntity> list;
36   - if (flag == 0)
37   - list = SocketClientLoader.load();
38   - else
39   - list = GatewayHttpLoader.load();
40   -
41   - if(null != list && list.size() > 0)
42   - handleProcess.handle(list);
43   - } catch (Exception e) {
44   - logger.error("", e);
45   - }
46   - }
  1 +package com.bsth.data.gpsdata_v2.thread;
  2 +
  3 +import com.bsth.data.gpsdata_v2.DataHandleProcess;
  4 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  5 +import com.bsth.data.gpsdata_v2.load.GatewayHttpLoader;
  6 +import com.bsth.data.gpsdata_v2.load.SocketClientLoader;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * Created by panzhao on 2017/1/11.
  16 + */
  17 +@Component
  18 +public class GpsDataLoaderThread extends Thread {
  19 +
  20 + Logger logger = LoggerFactory.getLogger(this.getClass());
  21 +
  22 + //0:从GPS客户端内存获取 -1:从网关获取
  23 + private static int flag = 0;
  24 +
  25 + public static void setFlag(int v) {
  26 + flag = v;
  27 + }
  28 +
  29 + @Autowired
  30 + DataHandleProcess handleProcess;
  31 +
  32 + @Override
  33 + public void run() {
  34 + try {
  35 + List<GpsEntity> list;
  36 + if (flag == 0)
  37 + list = SocketClientLoader.load();
  38 + else
  39 + list = GatewayHttpLoader.load();
  40 +
  41 + if(null != list && list.size() > 0)
  42 + handleProcess.handle(list);
  43 + } catch (Exception e) {
  44 + logger.error("", e);
  45 + }
  46 + }
47 47 }
48 48 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/thread/OfflineMonitorThread.java 0 → 100644
  1 +package com.bsth.data.gpsdata_v2.thread;
  2 +
  3 +import com.bsth.data.gpsdata_v2.GpsRealData;
  4 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  5 +import com.bsth.websocket.handler.SendUtils;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.util.Collection;
  12 +
  13 +/**
  14 + * GPS掉离线监控
  15 + * Created by panzhao on 2017/1/11.
  16 + */
  17 +@Component
  18 +public class OfflineMonitorThread extends Thread{
  19 +
  20 + @Autowired
  21 + GpsRealData gpsRealData;
  22 +
  23 + //掉线阈值
  24 + private final static int LOSE_TIME = 1000 * 60 * 10;
  25 +
  26 + Logger logger = LoggerFactory.getLogger(this.getClass());
  27 +
  28 + @Autowired
  29 + SendUtils sendUtils;
  30 +
  31 + //无任务时 离线阈值
  32 + //private final static int OFFLINE_TIME = 1000 * 60 * 10;
  33 +
  34 + @Override
  35 + public void run() {
  36 + try{
  37 + long t = System.currentTimeMillis();
  38 + Collection<GpsEntity> list = gpsRealData.all();
  39 +
  40 + String state;
  41 + for(GpsEntity gps : list){
  42 + state = gps.getAbnormalStatus();
  43 +
  44 + if(state != null && state.equals("offline"))
  45 + continue;
  46 +
  47 + if (t - gps.getTimestamp() > LOSE_TIME){
  48 + gps.offline();
  49 +
  50 + //通知页面有设备掉线
  51 + sendUtils.deviceOffline(gps);
  52 + }
  53 + }
  54 + }catch (Exception e){
  55 + logger.error("", e);
  56 + }
  57 + }
  58 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/CircleQueue.java
1   -package com.bsth.data.gpsdata_v2.utils;
2   -
3   -import java.util.Arrays;
4   -
5   -/**
6   - * 循环队列
7   - * Created by panzhao on 2016/12/23.
8   - */
9   -public class CircleQueue<T> {
10   -
11   - /**
12   - * (循环队列)数组的容量
13   - */
14   - public int capacity;
15   -
16   - /**
17   - * 数组:保存循环队列的元素
18   - */
19   - public Object[] elementData;
20   -
21   - /**
22   - * 头
23   - */
24   - public int head = 0;
25   -
26   - /**
27   - * 尾
28   - */
29   - public int tail = 0;
30   -
31   - /**
32   - * 以指定长度的数组来创建循环队列
33   - *
34   - * @param initSize
35   - */
36   - public CircleQueue(final int initSize) {
37   - capacity = initSize;
38   - elementData = new Object[capacity];
39   - }
40   -
41   - /**
42   - * 获取循环队列的大小
43   - */
44   - public int size() {
45   - if (isEmpty()) {
46   - return 0;
47   - } else if (isFull()) {
48   - return capacity;
49   - } else {
50   - return tail + 1;
51   - }
52   - }
53   -
54   - /**
55   - * 插入队尾一个元素
56   - */
57   - public void add(final T element) {
58   - if (isEmpty()) {
59   - elementData[0] = element;
60   - } else if (isFull()) {
61   - elementData[head] = element;
62   - head++;
63   - tail++;
64   - head = head == capacity ? 0 : head;
65   - tail = tail == capacity ? 0 : tail;
66   - } else {
67   - elementData[tail + 1] = element;
68   - tail++;
69   - }
70   - }
71   -
72   - public boolean isEmpty() {
73   - return tail == head && tail == 0 && elementData[tail] == null;
74   - }
75   -
76   - public boolean isFull() {
77   - return head != 0 && head - tail == 1 || head == 0 && tail == capacity - 1;
78   - }
79   -
80   - public void clear() {
81   - Arrays.fill(elementData, null);
82   - head = 0;
83   - tail = 0;
84   - }
85   -
86   - /**
87   - * @return 取 循环队列里的值(先进的index=0)
88   - */
89   - public Object[] getQueue() {
90   - final Object[] elementDataSort;
91   - final Object[] elementDataCopy = elementData.clone();
92   - if (isEmpty()) {
93   - elementDataSort = new Object[0];
94   - } else if (isFull()) {
95   - elementDataSort = new Object[capacity];
96   - int indexMax = capacity;
97   - int indexSort = 0;
98   - for (int i = head; i < indexMax;) {
99   - elementDataSort[indexSort] = elementDataCopy[i];
100   - indexSort++;
101   - i++;
102   - if (i == capacity) {
103   - i = 0;
104   - indexMax = head;
105   - }
106   - }
107   - } else {
108   - elementDataSort = new Object[tail + 1];
109   - for (int i = 0; i <= tail; i++) {
110   - elementDataSort[i] = elementDataCopy[i];
111   - }
112   - }
113   - return elementDataSort;
114   - }
115   -
116   - /**
117   - * 取最后一个值
118   - * @return
119   - */
120   - public T getTail(){
121   - return elementData[tail] == null?null:(T)elementData[tail];
122   - }
  1 +package com.bsth.data.gpsdata_v2.utils;
  2 +
  3 +import java.util.Arrays;
  4 +
  5 +/**
  6 + * 循环队列
  7 + * Created by panzhao on 2016/12/23.
  8 + */
  9 +public class CircleQueue<T> {
  10 +
  11 + /**
  12 + * (循环队列)数组的容量
  13 + */
  14 + public int capacity;
  15 +
  16 + /**
  17 + * 数组:保存循环队列的元素
  18 + */
  19 + public Object[] elementData;
  20 +
  21 + /**
  22 + * 头
  23 + */
  24 + public int head = 0;
  25 +
  26 + /**
  27 + * 尾
  28 + */
  29 + public int tail = 0;
  30 +
  31 + /**
  32 + * 以指定长度的数组来创建循环队列
  33 + *
  34 + * @param initSize
  35 + */
  36 + public CircleQueue(final int initSize) {
  37 + capacity = initSize;
  38 + elementData = new Object[capacity];
  39 + }
  40 +
  41 + /**
  42 + * 获取循环队列的大小
  43 + */
  44 + public int size() {
  45 + if (isEmpty()) {
  46 + return 0;
  47 + } else if (isFull()) {
  48 + return capacity;
  49 + } else {
  50 + return tail + 1;
  51 + }
  52 + }
  53 +
  54 + /**
  55 + * 插入队尾一个元素
  56 + */
  57 + public void add(final T element) {
  58 + if (isEmpty()) {
  59 + elementData[0] = element;
  60 + } else if (isFull()) {
  61 + elementData[head] = element;
  62 + head++;
  63 + tail++;
  64 + head = head == capacity ? 0 : head;
  65 + tail = tail == capacity ? 0 : tail;
  66 + } else {
  67 + elementData[tail + 1] = element;
  68 + tail++;
  69 + }
  70 + }
  71 +
  72 + public boolean isEmpty() {
  73 + return tail == head && tail == 0 && elementData[tail] == null;
  74 + }
  75 +
  76 + public boolean isFull() {
  77 + return head != 0 && head - tail == 1 || head == 0 && tail == capacity - 1;
  78 + }
  79 +
  80 + public void clear() {
  81 + Arrays.fill(elementData, null);
  82 + head = 0;
  83 + tail = 0;
  84 + }
  85 +
  86 + /**
  87 + * @return 取 循环队列里的值(先进的index=0)
  88 + */
  89 + public Object[] getQueue() {
  90 + final Object[] elementDataSort;
  91 + final Object[] elementDataCopy = elementData.clone();
  92 + if (isEmpty()) {
  93 + elementDataSort = new Object[0];
  94 + } else if (isFull()) {
  95 + elementDataSort = new Object[capacity];
  96 + int indexMax = capacity;
  97 + int indexSort = 0;
  98 + for (int i = head; i < indexMax;) {
  99 + elementDataSort[indexSort] = elementDataCopy[i];
  100 + indexSort++;
  101 + i++;
  102 + if (i == capacity) {
  103 + i = 0;
  104 + indexMax = head;
  105 + }
  106 + }
  107 + } else {
  108 + elementDataSort = new Object[tail + 1];
  109 + for (int i = 0; i <= tail; i++) {
  110 + elementDataSort[i] = elementDataCopy[i];
  111 + }
  112 + }
  113 + return elementDataSort;
  114 + }
  115 +
  116 + /**
  117 + * 取最后一个值
  118 + * @return
  119 + */
  120 + public T getTail(){
  121 + return elementData[tail] == null?null:(T)elementData[tail];
  122 + }
123 123 }
124 124 \ No newline at end of file
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/GeoUtils.java
1   -package com.bsth.data.gpsdata_v2.utils;
2   -
3   -import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
4   -import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
5   -import com.bsth.data.gpsdata_v2.entity.CtLineString;
6   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
7   -import com.bsth.data.gpsdata_v2.entity.PreconditionGeo;
8   -import com.bsth.data.gpsdata_v2.entity.StationRoute;
9   -import com.bsth.util.Geo.Bounds;
10   -import com.bsth.util.Geo.Point;
11   -import com.bsth.util.Geo.Polygon;
12   -
13   -import java.util.*;
14   -
15   -/**
16   - * Created by panzhao on 2016/12/23.
17   - */
18   -public class GeoUtils {
19   -
20   - private final static double EARTH_RADIUS = 6378137;
21   -
22   - private static StationRouteComp sComp = new StationRouteComp();
23   - /**
24   - * gps是否在路由上的某个站内
25   - *
26   - * @param gps
27   - * @param srs
28   - * @return
29   - */
30   - public static StationRoute gpsInStation(GpsEntity gps, List<StationRoute> srs) {
31   - List<StationRoute> rs = new ArrayList<>();
32   -
33   - Point point = new Point(gps.getLon(), gps.getLat());
34   - double distance;
35   -
36   - for (StationRoute sr : srs) {
37   - if (sr.getPolygon() == null) {
38   - //圆形
39   - distance = getDistance(sr.getPoint(), point);
40   -
41   - if (distance > sr.getRadius())
42   - continue;
43   -
44   - rs.add(sr);
45   - } else if(isPointInPolygon(point, sr.getPolygon())){
46   - rs.add(sr);
47   - }
48   - }
49   -
50   - if(rs.size() == 0)
51   - return null;
52   - else
53   - return findNearStation(rs, gps);
54   - }
55   -
56   - private static StationRoute findNearStation(List<StationRoute> rs, GpsEntity gps) {
57   - if(rs.size() > 1){
58   - //按路由顺序排序
59   - Collections.sort(rs, sComp);
60   -
61   - //上一个进出的站点
62   - StationRoute ps = GpsCacheData.prevStation(gps);
63   - if(null != ps){
64   - for(StationRoute s : rs){
65   - if(s.getRouteSort() >= ps.getRouteSort())
66   - return s;
67   - }
68   - }
69   - }
70   - return rs.get(0);
71   - }
72   -
73   -
74   - public static double getDistance(Point p1, Point p2) {
75   - double lng1 = getLoop(p1.getLon(), -180, 180), lat1 = getRange(
76   - p1.getLat(), -74, 74);
77   - double lng2 = getLoop(p2.getLon(), -180, 180), lat2 = getRange(
78   - p2.getLat(), -74, 74);
79   -
80   - double x1, x2, y1, y2;
81   - x1 = degreeToRad(lng1);
82   - y1 = degreeToRad(lat1);
83   - x2 = degreeToRad(lng2);
84   - y2 = degreeToRad(lat2);
85   - return EARTH_RADIUS
86   - * Math.acos((Math.sin(y1) * Math.sin(y2) + Math.cos(y1)
87   - * Math.cos(y2) * Math.cos(x2 - x1)));
88   - }
89   -
90   - private static double getLoop(double v, double a, double b) {
91   - while (v > b) {
92   - v -= b - a;
93   - }
94   - while (v < a) {
95   - v += b - a;
96   - }
97   - return v;
98   - }
99   -
100   - private static double getRange(double v, double a, double b) {
101   - v = Math.min(Math.max(v, a), b);
102   - return v;
103   - }
104   -
105   - private static double degreeToRad(double degree) {
106   - return Math.PI * degree / 180;
107   - }
108   -
109   - public static double getDistanceFromLine(CtLineString lineString, Point p){
110   - return getDistanceFromLine(lineString.getS(), lineString.getE(), p);
111   - }
112   -
113   - /**
114   - * 计算点 到 线的距离
115   - * @param line
116   - * @param p
117   - * @return
118   - */
119   - public static double getDistanceFromLine(Point s, Point e, Point p){
120   - double d1 = getDistance(s, p);
121   - double d2 = getDistance(p, e);
122   - double d3 = getDistance(s, e);
123   - double distance = 0;
124   -
125   - double alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3));
126   - double beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3));
127   -
128   - if(alpha>Math.PI/2) {
129   - distance = d1;
130   - }
131   - else if(beta > Math.PI/2) {
132   - distance = d2;
133   - }
134   - else {
135   - distance = Math.sin(alpha) * d1;
136   - }
137   - return distance;
138   - }
139   -
140   - /**
141   - * gps 是否在某个停车场内
142   - * @param gps
143   - * @return
144   - */
145   - public static String gpsInCarpark(GpsEntity gps){
146   - Point point = new Point(gps.getLon(), gps.getLat());
147   - Map<String, Polygon> carparkMap = GeoCacheData.tccMap;
148   -
149   - Set<String> codes = carparkMap.keySet();
150   - for(String code : codes){
151   - if(isPointInPolygon(point, carparkMap.get(code))){
152   - return code;
153   - }
154   - }
155   - return null;
156   - }
157   -
158   - /**
159   - * 是否在进站前置围栏内
160   - * @param gps
161   - * @return
162   - */
163   - public static String gpsInPremiseGeo(GpsEntity gps) {
164   - List<PreconditionGeo> list = GeoCacheData.premiseGeoMap.get(gps.getLineId()+"_"+gps.getUpDown());
165   -
166   - if(null == list || list.size()==0)
167   - return null;
168   -
169   - Point point = new Point(gps.getLon(), gps.getLat());
170   - for(PreconditionGeo p : list){
171   - if(isPointInPolygon(point, p.getPolygon())){
172   - return p.getStationCode();
173   - }
174   - }
175   - return null;
176   - }
177   -
178   - /**
179   - * 是否是有效的连续点
180   - * @param prevGps
181   - * @param gps
182   - * @return
183   - */
184   - public static boolean overdue(GpsEntity prevGps, GpsEntity gps) {
185   - return gps.getTimestamp() - prevGps.getTimestamp() < 120000;
186   - }
187   -
188   - /**
189   - * 计算2条直线的最短距离
190   - * @param p1
191   - * @param p2
192   - * @param p3
193   - * @param p4
194   - * @return
195   - */
196   - public static double getDistanceLineToLine(Point p1, Point p2, Point p3, Point p4){
197   - double distance;
198   - double x1 = p1.getLat(); //A点坐标(x1,y1,z1)
199   - double y1 = p1.getLon();
200   - double z1 = 0;
201   - double x2 = p2.getLat(); //B点坐标(x2,y2,z2)
202   - double y2 = p2.getLon();
203   - double z2 = 0;
204   - double x3 = p3.getLat(); //C点坐标(x3,y3,z3)
205   - double y3 = p3.getLon();
206   - double z3 = 0;
207   - double x4 = p4.getLat(); //D点坐标(x4,y4,z4)
208   - double y4 = p4.getLon();
209   - double z4 = 0;
210   -
211   - double a = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1);
212   - double b = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
213   - double c = -((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3)+(z1-z2)*(z1-z3));
214   -
215   - double d = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
216   - double e = (x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)+(z4-z3)*(z4-z3);
217   - double f = -((x1-x3)*(x4-x3)+(y1-y3)*(y4-y3)+(z1-z3)*(z4-z3));
218   -
219   - //平行
220   - if ((a*e-b*d)==0&&(b*d-a*e)==0)
221   - {
222   - double d1 = getDistance(p1, p3);
223   - double d2 = getDistance(p1, p4);
224   - distance = (d1<d2)?d1:d2;
225   - return distance;
226   - }
227   -
228   - double s = (b*f-e*c)/(a*e-b*d);
229   - double t = (a*f-d*c)/(b*d-a*e);
230   -
231   - //说明P点落在线段AB上,Q点落在线段CD上
232   - if(0<=s&&s<=1&&0<=t&&t<=1)
233   - {
234   - //2条线段的公垂线段PQ;
235   - //P点坐标
236   - double X = x1+s*(x2-x1);
237   - double Y = y1+s*(y2-y1);
238   - double Z = z1+s*(z2-z1);
239   - //Q点坐标
240   - double U = x3+t*(x4-x3);
241   - double V = y3+t*(y4-y3);
242   - double W = z3+t*(z4-z3);
243   -
244   - Point p = new Point(Y, X);
245   - Point q = new Point(V, U);
246   - distance = getDistance(p, q);
247   - }
248   - else
249   - {
250   - double d1 = getDistanceFromLine(p3,p4,p1);
251   - double d2 = getDistanceFromLine(p3,p4,p2);
252   - double d3 = getDistanceFromLine(p1,p2,p3);
253   - double d4 = getDistanceFromLine(p1,p2,p4);
254   - distance = (d1<d2)?d1:d2;
255   - distance = (distance<d3)?distance:d3;
256   - distance = (distance<d4)?distance:d4;
257   - }
258   -
259   - return distance;
260   - }
261   -
262   - /**
263   - * 计算点 到 线的垂直交点
264   - * @param lp1
265   - * @param lp2
266   - * @param p
267   - * @return
268   - */
269   - public static Point perpendularPoint(Point lp1, Point lp2, Point p){
270   - double a = lp1.getLat() - lp2.getLat(), b = lp2.getLon() - lp1.getLon(), c = lp1.getLon() * lp2.getLat() - lp2.getLon() * lp1.getLat();
271   - double lon = (Math.pow(b, 2) * p.getLon() - a * b * p.getLat() - a * c) / (Math.pow(a, 2) + Math.pow(b, 2));
272   - double lat = (Math.pow(a, 2) * p.getLat() - a * b * p.getLon() - b * c) / (Math.pow(a, 2) + Math.pow(b, 2));
273   -
274   - return new Point(lon, lat);
275   - }
276   -
277   - public static boolean isPointInRect(Point point, Bounds bounds) {
278   - Point sw = bounds.getSouthWest(); // 西南脚点
279   - Point ne = bounds.getNorthEast(); // 东北脚点
280   - return (point.getLon() >= sw.getLon() && point.getLon() <= ne.getLon()
281   - && point.getLat() >= sw.getLat() && point.getLat() <= ne
282   - .getLat());
283   - }
284   -
285   - public static boolean isPointInPolygon(Point point, Polygon polygon) {
286   - Bounds polygonBounds = polygon.getBounds();
287   - if (!isPointInRect(point, polygonBounds)) {
288   - return false;
289   - }
290   -
291   - List<Point> pts = polygon.getPoints();// 获取多边形点
292   -
293   - // 下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
294   - // 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
295   - // 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
296   -
297   - int N = pts.size();
298   - boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
299   - int intersectCount = 0;// cross points count of x
300   - double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
301   - Point p1, p2;// neighbour bound vertices
302   - Point p = point; // 测试点
303   -
304   - p1 = pts.get(0);// left vertex
305   - for (int i = 1; i <= N; ++i) {// check all rays
306   - if (p.equals(p1)) {
307   - return boundOrVertex;// p is an vertex
308   - }
309   -
310   - p2 = pts.get(i % N);// right vertex
311   - if (p.getLat() < Math.min(p1.getLat(), p2.getLat())
312   - || p.getLat() > Math.max(p1.getLat(), p2.getLat())) {// ray
313   - // is
314   - // outside
315   - // of
316   - // our
317   - // interests
318   - p1 = p2;
319   - continue;// next ray left point
320   - }
321   -
322   - if (p.getLat() > Math.min(p1.getLat(), p2.getLat())
323   - && p.getLat() < Math.max(p1.getLat(), p2.getLat())) {// ray
324   - // is
325   - // crossing
326   - // over
327   - // by
328   - // the
329   - // algorithm
330   - // (common
331   - // part
332   - // of)
333   - if (p.getLon() <= Math.max(p1.getLon(), p2.getLon())) {// x is
334   - // before
335   - // of
336   - // ray
337   - if (p1.getLat() == p2.getLat()
338   - && p.getLon() >= Math.min(p1.getLon(), p2.getLon())) {// overlies
339   - // on
340   - // a
341   - // horizontal
342   - // ray
343   - return boundOrVertex;
344   - }
345   -
346   - if (p1.getLon() == p2.getLon()) {// ray is vertical
347   - if (p1.getLon() == p.getLon()) {// overlies on a
348   - // vertical ray
349   - return boundOrVertex;
350   - } else {// before ray
351   - ++intersectCount;
352   - }
353   - } else {// cross point on the left side
354   - double xinters = (p.getLat() - p1.getLat())
355   - * (p2.getLon() - p1.getLon())
356   - / (p2.getLat() - p1.getLat()) + p1.getLon();// cross
357   - // point
358   - // of
359   - // lng
360   - if (Math.abs(p.getLon() - xinters) < precision) {// overlies
361   - // on
362   - // a
363   - // ray
364   - return boundOrVertex;
365   - }
366   -
367   - if (p.getLon() < xinters) {// before ray
368   - ++intersectCount;
369   - }
370   - }
371   - }
372   - } else {// special case when ray is crossing through the vertex
373   - if (p.getLat() == p2.getLat() && p.getLon() <= p2.getLon()) {// p
374   - // crossing
375   - // over
376   - // p2
377   - Point p3 = pts.get((i + 1) % N); // next vertex
378   - if (p.getLat() >= Math.min(p1.getLat(), p3.getLat())
379   - && p.getLat() <= Math.max(p1.getLat(), p3.getLat())) {// p.lat
380   - // lies
381   - // between
382   - // p1.lat
383   - // &
384   - // p3.lat
385   - ++intersectCount;
386   - } else {
387   - intersectCount += 2;
388   - }
389   - }
390   - }
391   - p1 = p2;// next ray left point
392   - }
393   -
394   - if (intersectCount % 2 == 0) {// 偶数在多边形外
395   - return false;
396   - } else { // 奇数在多边形内
397   - return true;
398   - }
399   - }
400   -
401   -}
  1 +package com.bsth.data.gpsdata_v2.utils;
  2 +
  3 +import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
  4 +import com.bsth.data.gpsdata_v2.cache.GpsCacheData;
  5 +import com.bsth.data.gpsdata_v2.entity.CtLineString;
  6 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  7 +import com.bsth.data.gpsdata_v2.entity.PreconditionGeo;
  8 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  9 +import com.bsth.util.Geo.Bounds;
  10 +import com.bsth.util.Geo.Point;
  11 +import com.bsth.util.Geo.Polygon;
  12 +
  13 +import java.util.*;
  14 +
  15 +/**
  16 + * Created by panzhao on 2016/12/23.
  17 + */
  18 +public class GeoUtils {
  19 +
  20 + private final static double EARTH_RADIUS = 6378137;
  21 +
  22 + private static StationRouteComp sComp = new StationRouteComp();
  23 + /**
  24 + * gps是否在路由上的某个站内
  25 + *
  26 + * @param gps
  27 + * @param srs
  28 + * @return
  29 + */
  30 + public static StationRoute gpsInStation(GpsEntity gps, List<StationRoute> srs) {
  31 + List<StationRoute> rs = new ArrayList<>();
  32 +
  33 + Point point = new Point(gps.getLon(), gps.getLat());
  34 + double distance;
  35 +
  36 + for (StationRoute sr : srs) {
  37 + if (sr.getPolygon() == null) {
  38 + //圆形
  39 + distance = getDistance(sr.getPoint(), point);
  40 +
  41 + if (distance > sr.getRadius())
  42 + continue;
  43 +
  44 + rs.add(sr);
  45 + } else if(isPointInPolygon(point, sr.getPolygon())){
  46 + rs.add(sr);
  47 + }
  48 + }
  49 +
  50 + if(rs.size() == 0)
  51 + return null;
  52 + else
  53 + return findNearStation(rs, gps);
  54 + }
  55 +
  56 + private static StationRoute findNearStation(List<StationRoute> rs, GpsEntity gps) {
  57 + if(rs.size() > 1){
  58 + //按路由顺序排序
  59 + Collections.sort(rs, sComp);
  60 +
  61 + //上一个进出的站点
  62 + StationRoute ps = GpsCacheData.prevStation(gps);
  63 + if(null != ps){
  64 + for(StationRoute s : rs){
  65 + if(s.getRouteSort() >= ps.getRouteSort())
  66 + return s;
  67 + }
  68 + }
  69 + }
  70 + return rs.get(0);
  71 + }
  72 +
  73 +
  74 + public static double getDistance(Point p1, Point p2) {
  75 + double lng1 = getLoop(p1.getLon(), -180, 180), lat1 = getRange(
  76 + p1.getLat(), -74, 74);
  77 + double lng2 = getLoop(p2.getLon(), -180, 180), lat2 = getRange(
  78 + p2.getLat(), -74, 74);
  79 +
  80 + double x1, x2, y1, y2;
  81 + x1 = degreeToRad(lng1);
  82 + y1 = degreeToRad(lat1);
  83 + x2 = degreeToRad(lng2);
  84 + y2 = degreeToRad(lat2);
  85 + return EARTH_RADIUS
  86 + * Math.acos((Math.sin(y1) * Math.sin(y2) + Math.cos(y1)
  87 + * Math.cos(y2) * Math.cos(x2 - x1)));
  88 + }
  89 +
  90 + private static double getLoop(double v, double a, double b) {
  91 + while (v > b) {
  92 + v -= b - a;
  93 + }
  94 + while (v < a) {
  95 + v += b - a;
  96 + }
  97 + return v;
  98 + }
  99 +
  100 + private static double getRange(double v, double a, double b) {
  101 + v = Math.min(Math.max(v, a), b);
  102 + return v;
  103 + }
  104 +
  105 + private static double degreeToRad(double degree) {
  106 + return Math.PI * degree / 180;
  107 + }
  108 +
  109 + public static double getDistanceFromLine(CtLineString lineString, Point p){
  110 + return getDistanceFromLine(lineString.getS(), lineString.getE(), p);
  111 + }
  112 +
  113 + /**
  114 + * 计算点 到 线的距离
  115 + * @param line
  116 + * @param p
  117 + * @return
  118 + */
  119 + public static double getDistanceFromLine(Point s, Point e, Point p){
  120 + double d1 = getDistance(s, p);
  121 + double d2 = getDistance(p, e);
  122 + double d3 = getDistance(s, e);
  123 + double distance = 0;
  124 +
  125 + double alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3));
  126 + double beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3));
  127 +
  128 + if(alpha>Math.PI/2) {
  129 + distance = d1;
  130 + }
  131 + else if(beta > Math.PI/2) {
  132 + distance = d2;
  133 + }
  134 + else {
  135 + distance = Math.sin(alpha) * d1;
  136 + }
  137 + return distance;
  138 + }
  139 +
  140 + /**
  141 + * gps 是否在某个停车场内
  142 + * @param gps
  143 + * @return
  144 + */
  145 + public static String gpsInCarpark(GpsEntity gps){
  146 + Point point = new Point(gps.getLon(), gps.getLat());
  147 + Map<String, Polygon> carparkMap = GeoCacheData.tccMap;
  148 +
  149 + Set<String> codes = carparkMap.keySet();
  150 + for(String code : codes){
  151 + if(isPointInPolygon(point, carparkMap.get(code))){
  152 + return code;
  153 + }
  154 + }
  155 + return null;
  156 + }
  157 +
  158 + /**
  159 + * 是否在进站前置围栏内
  160 + * @param gps
  161 + * @return
  162 + */
  163 + public static String gpsInPremiseGeo(GpsEntity gps) {
  164 + List<PreconditionGeo> list = GeoCacheData.premiseGeoMap.get(gps.getLineId()+"_"+gps.getUpDown());
  165 +
  166 + if(null == list || list.size()==0)
  167 + return null;
  168 +
  169 + Point point = new Point(gps.getLon(), gps.getLat());
  170 + for(PreconditionGeo p : list){
  171 + if(isPointInPolygon(point, p.getPolygon())){
  172 + return p.getStationCode();
  173 + }
  174 + }
  175 + return null;
  176 + }
  177 +
  178 + /**
  179 + * 是否是有效的连续点
  180 + * @param prevGps
  181 + * @param gps
  182 + * @return
  183 + */
  184 + public static boolean overdue(GpsEntity prevGps, GpsEntity gps) {
  185 + return gps.getTimestamp() - prevGps.getTimestamp() < 120000;
  186 + }
  187 +
  188 + /**
  189 + * 计算2条直线的最短距离
  190 + * @param p1
  191 + * @param p2
  192 + * @param p3
  193 + * @param p4
  194 + * @return
  195 + */
  196 + public static double getDistanceLineToLine(Point p1, Point p2, Point p3, Point p4){
  197 + double distance;
  198 + double x1 = p1.getLat(); //A点坐标(x1,y1,z1)
  199 + double y1 = p1.getLon();
  200 + double z1 = 0;
  201 + double x2 = p2.getLat(); //B点坐标(x2,y2,z2)
  202 + double y2 = p2.getLon();
  203 + double z2 = 0;
  204 + double x3 = p3.getLat(); //C点坐标(x3,y3,z3)
  205 + double y3 = p3.getLon();
  206 + double z3 = 0;
  207 + double x4 = p4.getLat(); //D点坐标(x4,y4,z4)
  208 + double y4 = p4.getLon();
  209 + double z4 = 0;
  210 +
  211 + double a = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1);
  212 + double b = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
  213 + double c = -((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3)+(z1-z2)*(z1-z3));
  214 +
  215 + double d = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
  216 + double e = (x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)+(z4-z3)*(z4-z3);
  217 + double f = -((x1-x3)*(x4-x3)+(y1-y3)*(y4-y3)+(z1-z3)*(z4-z3));
  218 +
  219 + //平行
  220 + if ((a*e-b*d)==0&&(b*d-a*e)==0)
  221 + {
  222 + double d1 = getDistance(p1, p3);
  223 + double d2 = getDistance(p1, p4);
  224 + distance = (d1<d2)?d1:d2;
  225 + return distance;
  226 + }
  227 +
  228 + double s = (b*f-e*c)/(a*e-b*d);
  229 + double t = (a*f-d*c)/(b*d-a*e);
  230 +
  231 + //说明P点落在线段AB上,Q点落在线段CD上
  232 + if(0<=s&&s<=1&&0<=t&&t<=1)
  233 + {
  234 + //2条线段的公垂线段PQ;
  235 + //P点坐标
  236 + double X = x1+s*(x2-x1);
  237 + double Y = y1+s*(y2-y1);
  238 + double Z = z1+s*(z2-z1);
  239 + //Q点坐标
  240 + double U = x3+t*(x4-x3);
  241 + double V = y3+t*(y4-y3);
  242 + double W = z3+t*(z4-z3);
  243 +
  244 + Point p = new Point(Y, X);
  245 + Point q = new Point(V, U);
  246 + distance = getDistance(p, q);
  247 + }
  248 + else
  249 + {
  250 + double d1 = getDistanceFromLine(p3,p4,p1);
  251 + double d2 = getDistanceFromLine(p3,p4,p2);
  252 + double d3 = getDistanceFromLine(p1,p2,p3);
  253 + double d4 = getDistanceFromLine(p1,p2,p4);
  254 + distance = (d1<d2)?d1:d2;
  255 + distance = (distance<d3)?distance:d3;
  256 + distance = (distance<d4)?distance:d4;
  257 + }
  258 +
  259 + return distance;
  260 + }
  261 +
  262 + /**
  263 + * 计算点 到 线的垂直交点
  264 + * @param lp1
  265 + * @param lp2
  266 + * @param p
  267 + * @return
  268 + */
  269 + public static Point perpendularPoint(Point lp1, Point lp2, Point p){
  270 + double a = lp1.getLat() - lp2.getLat(), b = lp2.getLon() - lp1.getLon(), c = lp1.getLon() * lp2.getLat() - lp2.getLon() * lp1.getLat();
  271 + double lon = (Math.pow(b, 2) * p.getLon() - a * b * p.getLat() - a * c) / (Math.pow(a, 2) + Math.pow(b, 2));
  272 + double lat = (Math.pow(a, 2) * p.getLat() - a * b * p.getLon() - b * c) / (Math.pow(a, 2) + Math.pow(b, 2));
  273 +
  274 + return new Point(lon, lat);
  275 + }
  276 +
  277 + public static boolean isPointInRect(Point point, Bounds bounds) {
  278 + Point sw = bounds.getSouthWest(); // 西南脚点
  279 + Point ne = bounds.getNorthEast(); // 东北脚点
  280 + return (point.getLon() >= sw.getLon() && point.getLon() <= ne.getLon()
  281 + && point.getLat() >= sw.getLat() && point.getLat() <= ne
  282 + .getLat());
  283 + }
  284 +
  285 + public static boolean isPointInPolygon(Point point, Polygon polygon) {
  286 + Bounds polygonBounds = polygon.getBounds();
  287 + if (!isPointInRect(point, polygonBounds)) {
  288 + return false;
  289 + }
  290 +
  291 + List<Point> pts = polygon.getPoints();// 获取多边形点
  292 +
  293 + // 下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
  294 + // 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
  295 + // 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
  296 +
  297 + int N = pts.size();
  298 + boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
  299 + int intersectCount = 0;// cross points count of x
  300 + double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
  301 + Point p1, p2;// neighbour bound vertices
  302 + Point p = point; // 测试点
  303 +
  304 + p1 = pts.get(0);// left vertex
  305 + for (int i = 1; i <= N; ++i) {// check all rays
  306 + if (p.equals(p1)) {
  307 + return boundOrVertex;// p is an vertex
  308 + }
  309 +
  310 + p2 = pts.get(i % N);// right vertex
  311 + if (p.getLat() < Math.min(p1.getLat(), p2.getLat())
  312 + || p.getLat() > Math.max(p1.getLat(), p2.getLat())) {// ray
  313 + // is
  314 + // outside
  315 + // of
  316 + // our
  317 + // interests
  318 + p1 = p2;
  319 + continue;// next ray left point
  320 + }
  321 +
  322 + if (p.getLat() > Math.min(p1.getLat(), p2.getLat())
  323 + && p.getLat() < Math.max(p1.getLat(), p2.getLat())) {// ray
  324 + // is
  325 + // crossing
  326 + // over
  327 + // by
  328 + // the
  329 + // algorithm
  330 + // (common
  331 + // part
  332 + // of)
  333 + if (p.getLon() <= Math.max(p1.getLon(), p2.getLon())) {// x is
  334 + // before
  335 + // of
  336 + // ray
  337 + if (p1.getLat() == p2.getLat()
  338 + && p.getLon() >= Math.min(p1.getLon(), p2.getLon())) {// overlies
  339 + // on
  340 + // a
  341 + // horizontal
  342 + // ray
  343 + return boundOrVertex;
  344 + }
  345 +
  346 + if (p1.getLon() == p2.getLon()) {// ray is vertical
  347 + if (p1.getLon() == p.getLon()) {// overlies on a
  348 + // vertical ray
  349 + return boundOrVertex;
  350 + } else {// before ray
  351 + ++intersectCount;
  352 + }
  353 + } else {// cross point on the left side
  354 + double xinters = (p.getLat() - p1.getLat())
  355 + * (p2.getLon() - p1.getLon())
  356 + / (p2.getLat() - p1.getLat()) + p1.getLon();// cross
  357 + // point
  358 + // of
  359 + // lng
  360 + if (Math.abs(p.getLon() - xinters) < precision) {// overlies
  361 + // on
  362 + // a
  363 + // ray
  364 + return boundOrVertex;
  365 + }
  366 +
  367 + if (p.getLon() < xinters) {// before ray
  368 + ++intersectCount;
  369 + }
  370 + }
  371 + }
  372 + } else {// special case when ray is crossing through the vertex
  373 + if (p.getLat() == p2.getLat() && p.getLon() <= p2.getLon()) {// p
  374 + // crossing
  375 + // over
  376 + // p2
  377 + Point p3 = pts.get((i + 1) % N); // next vertex
  378 + if (p.getLat() >= Math.min(p1.getLat(), p3.getLat())
  379 + && p.getLat() <= Math.max(p1.getLat(), p3.getLat())) {// p.lat
  380 + // lies
  381 + // between
  382 + // p1.lat
  383 + // &
  384 + // p3.lat
  385 + ++intersectCount;
  386 + } else {
  387 + intersectCount += 2;
  388 + }
  389 + }
  390 + }
  391 + p1 = p2;// next ray left point
  392 + }
  393 +
  394 + if (intersectCount % 2 == 0) {// 偶数在多边形外
  395 + return false;
  396 + } else { // 奇数在多边形内
  397 + return true;
  398 + }
  399 + }
  400 +
  401 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/GpsDataRecovery.java
... ... @@ -59,7 +59,7 @@ public class GpsDataRecovery implements ApplicationContextAware {
59 59 for (String nbbm : keys) {
60 60 Collections.sort(listMap.get(nbbm), comp);
61 61 threadPool.submit(new RecoveryThread(listMap.get(nbbm), count));
62   - /*if(nbbm.equals("W2H-015"))
  62 + /*if(nbbm.equals("S0L-065"))
63 63 new RecoveryThread(listMap.get(nbbm), count).run();*/
64 64 /*if(lineId.equals("60028"))
65 65 new RecoveryThread(listMap.get(lineId), count).run();*/
... ... @@ -151,6 +151,9 @@ public class GpsDataRecovery implements ApplicationContextAware {
151 151 for (GpsEntity gps : list) {
152 152 try {
153 153  
  154 + /*if(gps.getTimestamp() >= 1511386080000L)
  155 + System.out.println("aaa");*/
  156 +
154 157 gpsStateProcess.process(gps);//状态处理
155 158 stationInsideProcess.process(gps);//场站内外判定
156 159  
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/GpsDataUtils.java
1   -package com.bsth.data.gpsdata_v2.utils;
2   -
3   -import com.bsth.data.gpsdata_v2.entity.GpsEntity;
4   -import org.slf4j.Logger;
5   -import org.slf4j.LoggerFactory;
6   -
7   -import java.util.ArrayList;
8   -import java.util.List;
9   -
10   -/**
11   - * Created by panzhao on 2017/11/15.
12   - */
13   -public class GpsDataUtils {
14   -
15   - static Logger logger = LoggerFactory.getLogger(GpsDataUtils.class);
16   -
17   - /**
18   - * 过滤无效的gps点位
19   - *
20   - * @param list
21   - * @return
22   - */
23   - public static List<GpsEntity> clearInvalid(List<GpsEntity> list) {
24   - List<GpsEntity> rs = new ArrayList<>();
25   -
26   - try {
27   - for (GpsEntity gps : list) {
28   - if (gps.getValid() == 0)
29   - rs.add(gps);
30   - }
31   -
32   - if (rs.size() < list.size())
33   - logger.info("过滤无效的点位 : " + (list.size() - rs.size()));
34   - } catch (Exception e) {
35   - logger.error("", e);
36   - rs = list;
37   - }
38   - return rs;
39   - }
40   -}
  1 +package com.bsth.data.gpsdata_v2.utils;
  2 +
  3 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +
  7 +import java.util.ArrayList;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * Created by panzhao on 2017/11/15.
  12 + */
  13 +public class GpsDataUtils {
  14 +
  15 + static Logger logger = LoggerFactory.getLogger(GpsDataUtils.class);
  16 +
  17 + /**
  18 + * 过滤无效的gps点位
  19 + *
  20 + * @param list
  21 + * @return
  22 + */
  23 + public static List<GpsEntity> clearInvalid(List<GpsEntity> list) {
  24 + List<GpsEntity> rs = new ArrayList<>();
  25 +
  26 + try {
  27 + for (GpsEntity gps : list) {
  28 + if (gps.getValid() == 0)
  29 + rs.add(gps);
  30 + }
  31 +
  32 + if (rs.size() < list.size())
  33 + logger.info("过滤无效的点位 : " + (list.size() - rs.size()));
  34 + } catch (Exception e) {
  35 + logger.error("", e);
  36 + rs = list;
  37 + }
  38 + return rs;
  39 + }
  40 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/SignalSchPlanMatcher.java 0 → 100644
  1 +package com.bsth.data.gpsdata_v2.utils;
  2 +
  3 +import com.bsth.data.gpsdata_v2.entity.GpsEntity;
  4 +import com.bsth.data.schedule.DayOfSchedule;
  5 +import com.bsth.data.schedule.ScheduleComparator;
  6 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  7 +import org.apache.commons.lang3.StringUtils;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import java.util.Collections;
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * 班次匹配器
  18 + * Created by panzhao on 2016/12/31.
  19 + */
  20 +@Component
  21 +public class SignalSchPlanMatcher {
  22 +
  23 + @Autowired
  24 + DayOfSchedule dayOfSchedule;
  25 +
  26 + static ScheduleComparator.DFSJ schComp = new ScheduleComparator.DFSJ();
  27 +
  28 + Logger log = LoggerFactory.getLogger(this.getClass());
  29 +
  30 + /**
  31 + * 发车信号匹配
  32 + * @param gps
  33 + * @param sch
  34 + * @return
  35 + */
  36 + public boolean outMatch(GpsEntity gps, ScheduleRealInfo sch){
  37 + long t = gps.getTimestamp();
  38 + if(t < sch.getDfsjT())
  39 + return true;
  40 +
  41 + try{
  42 + //晚于待发时间 半小时 ,匹配一下最佳的班次
  43 + if(t - sch.getDfsjT() > 1000 * 60 * 30){
  44 + ScheduleRealInfo near = searchNearOut(gps);
  45 +
  46 + if(null != near && !near.getId().equals(sch.getId())){
  47 + dayOfSchedule.addExecPlan(near);
  48 + return false;
  49 + }
  50 + }
  51 +
  52 + }catch (Exception e){
  53 + log.error("", e);
  54 + }
  55 + return true;
  56 + /*try{
  57 + //会不会是分班没有完成
  58 + if(sch.getBcType().equals("in") && t - sch.getDfsjT() > 1000 * 60 * 20){
  59 + ScheduleRealInfo fbFirst = dayOfSchedule.nextByBcType(sch, "normal");
  60 +
  61 + if(fbFirst == null || !fbFirst.getQdzCode().equals(gps.getStopNo()))
  62 + return;
  63 +
  64 + long dt = fbFirst.getDfsjT();
  65 + //晚于待发前4分钟 -执行分班的首个营运
  66 + if(dt - t < 1000 * 60 * 4){
  67 + dayOfSchedule.addExecPlan(fbFirst);
  68 + return;
  69 + }
  70 + }
  71 +
  72 + //线路编码不匹配
  73 + if("out".equals(sch.getBcType()) && !sch.getXlBm().equals(gps.getLineId())){
  74 + ScheduleRealInfo nextOut = dayOfSchedule.nextByBcType(sch, "out");
  75 + if(nextOut != null && nextOut.getXlBm().equals(gps.getLineId())
  76 + && fcSpace(sch, gps) > fcSpace(nextOut, gps)){
  77 + dayOfSchedule.addExecPlan(nextOut);
  78 + return;
  79 + }
  80 + }
  81 + }catch (Exception e){
  82 + log.error("", e);
  83 + }
  84 +
  85 + //下一个相同走向的班次
  86 + ScheduleRealInfo next = dayOfSchedule.nextSame(sch);
  87 + if(next == null || !next.getQdzCode().equals(sch.getQdzCode()))
  88 + return;
  89 +
  90 + //晚于班次间隔百分之70,跳下一个班次
  91 + double s = (int) (next.getDfsjT() - sch.getDfsjT());
  92 + double r = (int) (t - sch.getDfsjT());
  93 + if(r / s > 0.7){
  94 + if(dayOfSchedule.addExecPlan(next))
  95 + outMatch(gps, next);
  96 + }*/
  97 + }
  98 +
  99 + /**
  100 + * 搜索一个离发车信号最近的班次
  101 + * @param gps
  102 + * @return
  103 + */
  104 + private ScheduleRealInfo searchNearOut(GpsEntity gps) {
  105 + List<ScheduleRealInfo> list = dayOfSchedule.findByNbbm(gps.getNbbm());
  106 + //排序
  107 + Collections.sort(list, schComp);
  108 +
  109 + ScheduleRealInfo near = null;
  110 + int diff, minDiff=-1;
  111 + for(ScheduleRealInfo sch : list){
  112 +
  113 + if(StringUtils.isNotEmpty(sch.getFcsjActual()))
  114 + continue;
  115 +
  116 + if(StringUtils.isNotEmpty(sch.getZdsjActual()))
  117 + continue;
  118 +
  119 + diff = (int) Math.abs(gps.getTimestamp() - sch.getDfsjT());
  120 + if(null == near || diff < minDiff){
  121 + near = sch;
  122 + minDiff = diff;
  123 + }
  124 + }
  125 + return near;
  126 + }
  127 +}
... ...
src/main/java/com/bsth/data/gpsdata_v2/utils/StationRouteComp.java
1   -package com.bsth.data.gpsdata_v2.utils;
2   -
3   -
4   -import com.bsth.data.gpsdata_v2.entity.StationRoute;
5   -
6   -import java.util.Comparator;
7   -
8   -/**
9   - * Created by panzhao on 2016/12/24.
10   - */
11   -public class StationRouteComp implements Comparator<StationRoute>{
12   - @Override
13   - public int compare(StationRoute s1, StationRoute s2) {
14   - return s1.getRouteSort() - s2.getRouteSort();
15   - }
16   -}
  1 +package com.bsth.data.gpsdata_v2.utils;
  2 +
  3 +
  4 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  5 +
  6 +import java.util.Comparator;
  7 +
  8 +/**
  9 + * Created by panzhao on 2016/12/24.
  10 + */
  11 +public class StationRouteComp implements Comparator<StationRoute>{
  12 + @Override
  13 + public int compare(StationRoute s1, StationRoute s2) {
  14 + return s1.getRouteSort() - s2.getRouteSort();
  15 + }
  16 +}
... ...
src/main/java/com/bsth/data/schedule/SchAttrCalculator.java
... ... @@ -219,7 +219,7 @@ public class SchAttrCalculator {
219 219 boolean limitPark = StringUtils.isNotEmpty(park);
220 220  
221 221 ScheduleRealInfo sch, prev = null;
222   - for(int i = list.size() - 1; i > 0; i --){
  222 + for(int i = list.size() - 1; i >= 0; i --){
223 223 sch = list.get(i);
224 224  
225 225 //如果是出站既出场,忽略出场班次
... ...
src/main/java/com/bsth/data/summary/service/impl/DestroySituationServiceImpl.java
... ... @@ -29,6 +29,34 @@ public class DestroySituationServiceImpl extends BaseServiceImpl&lt;DestroySituatio
29 29 Logger logger = LoggerFactory.getLogger(this.getClass());
30 30  
31 31 @Override
  32 + public Iterable<DestroySituation> list(Map<String, Object> map) {
  33 + List<DestroySituation> list = (List<DestroySituation>) super.list(map);
  34 +
  35 + //排序
  36 + Collections.sort(list, new Comparator<DestroySituation>() {
  37 + @Override
  38 + public int compare(DestroySituation o1, DestroySituation o2) {
  39 + int i = o1.getRq().compareTo(o2.getRq());
  40 + if(i != 0)
  41 + return i;
  42 +
  43 + i = o1.getLineName().compareTo(o2.getLineName());
  44 + if(i != 0)
  45 + return i;
  46 +
  47 + i = (int) (o1.getT() - o2.getT());
  48 + if(i != 0)
  49 + return i;
  50 +
  51 + i = o1.getReason().compareTo(o2.getReason());
  52 +
  53 + return i;
  54 + }
  55 + });
  56 + return list;
  57 + }
  58 +
  59 + @Override
32 60 public void excel(Map<String, Object> map, HttpServletRequest request, HttpServletResponse response) {
33 61 try {
34 62 map.put("rq_le", CustomStringUtils.maxEndTime(map.get("rq_ge").toString()
... ... @@ -46,7 +74,21 @@ public class DestroySituationServiceImpl extends BaseServiceImpl&lt;DestroySituatio
46 74 Collections.sort(list, new Comparator<DestroySituation>() {
47 75 @Override
48 76 public int compare(DestroySituation o1, DestroySituation o2) {
49   - return (int) (o1.getT() - o2.getT());
  77 + int i = o1.getRq().compareTo(o2.getRq());
  78 + if(i != 0)
  79 + return i;
  80 +
  81 + i = o1.getLineName().compareTo(o2.getLineName());
  82 + if(i != 0)
  83 + return i;
  84 +
  85 + i = (int) (o1.getT() - o2.getT());
  86 + if(i != 0)
  87 + return i;
  88 +
  89 + i = o1.getReason().compareTo(o2.getReason());
  90 +
  91 + return i;
50 92 }
51 93 });
52 94  
... ...
src/main/java/com/bsth/repository/oil/YlbRepository.java
... ... @@ -46,6 +46,14 @@ public interface YlbRepository extends BaseRepository&lt;Ylb, Integer&gt;{
46 46 + " and y.xlbm like %?4% and y.nbbm like %?5%",nativeQuery=true)
47 47 List<Ylb> listMaxRqJcsx(String rq,String gsbm,String fgsbm,String xlbm,String nbbm);
48 48  
  49 + @Query(value="select * from bsth_c_ylb where to_days(?1) -to_days(rq) <30 "
  50 + + " and rq< ?1 and ssgsdm like %?2%"
  51 + + " and fgsdm like %?3% and xlbm like %?4% and nbbm like %?5% "
  52 + + " order by nbbm , rq desc,jcsx desc",nativeQuery=true)
  53 + List<Ylb> listByRqJcsx(String rq,String gsbm,String fgsbm,String xlbm,String nbbm);
  54 +
  55 +
  56 +
49 57 /**
50 58 * 当天YLB信息
51 59 * @param rq
... ...
src/main/java/com/bsth/service/oil/impl/YlbServiceImpl.java
... ... @@ -118,8 +118,8 @@ public class YlbServiceImpl extends BaseServiceImpl&lt;Ylb,Integer&gt; implements YlbS
118 118 //当天YLXXB信息
119 119 // List<Ylxxb> ylxxList=ylxxbRepository.obtainYlxx(rq);
120 120 //前一天所有车辆最后进场班次信息
121   -// List<Ylb> ylListBe=repository.obtainYlbefore(rq,"","","","");
122   - List<Ylb> ylListBe=repository.listMaxRqJcsx(rq, "", "", "", "");
  121 + List<Ylb> ylListBe=this.listByRqJcsx(rq,"","","","");
  122 +// List<Ylb> ylListBe=repository.listMaxRqJcsx(rq, "", "", "", "");
123 123 List<Cyl> clyList=cylRepository.obtainCyl("","");
124 124 //从排班表中计算出行驶的总里程
125 125 List<Map<String,Object>> listpb=scheduleRealInfoService.yesterdayDataList("", rq, "", "", "", "");
... ... @@ -269,8 +269,8 @@ public class YlbServiceImpl extends BaseServiceImpl&lt;Ylb,Integer&gt; implements YlbS
269 269 List<Ylxxb> ylxxList = ylxxbRepository.obtainYlxx(rq, 0,gsbm);
270 270  
271 271 // 前一天所有车辆最后进场班次信息
272   -// List<Ylb> ylListBe = repository.obtainYlbefore(rq, gsbm, fgsbm, line, nbbm);
273   - List<Ylb> ylListBe =repository.listMaxRqJcsx(rq, gsbm, fgsbm, line, nbbm);
  272 + List<Ylb> ylListBe = this.listByRqJcsx(rq, gsbm, fgsbm, line, nbbm);
  273 +// List<Ylb> ylListBe =repository.listMaxRqJcsx(rq, gsbm, fgsbm, line, nbbm);
274 274  
275 275 List<Cyl> clyList = cylRepository.obtainCyl(nbbm,gsbm);
276 276  
... ... @@ -727,7 +727,7 @@ public class YlbServiceImpl extends BaseServiceImpl&lt;Ylb,Integer&gt; implements YlbS
727 727 nbbm=map.get("nbbm_eq").toString();
728 728 }
729 729 // List<Ylb> ylListBe=repository.obtainYlbefore(rq, gsbm, "", xlbm, nbbm);
730   - List<Ylb> ylListBe=repository.listMaxRqJcsx(rq, gsbm, fgsbm, xlbm, nbbm);
  730 + List<Ylb> ylListBe=this.listByRqJcsx(rq, gsbm, fgsbm, xlbm, nbbm);
731 731 List<Ylb> ylbList=this.listOrderBy(rq,gsbm,fgsbm,xlbm,nbbm,"nbbm");
732 732 // repository.obtainYl(rq,gsbm,fgsbm,xlbm,nbbm,"nbbm");
733 733 // List<Ylxxb> ylxxbList=ylxxbRepository.obtainYlxx(rq,0,gsbm);
... ... @@ -1653,9 +1653,17 @@ public class YlbServiceImpl extends BaseServiceImpl&lt;Ylb,Integer&gt; implements YlbS
1653 1653 return newMap;
1654 1654 }
1655 1655  
1656   - public List<Ylb> listByRqJcsx(String rq,String gsdm,String fgsdm,String xlbm,String nbbm,
1657   - String px) {
1658   -
1659   - return null;
  1656 + public List<Ylb> listByRqJcsx(String rq,String gsdm,String fgsdm,String xlbm,String nbbm) {
  1657 + List<Ylb> list=repository.listByRqJcsx(rq, gsdm, fgsdm, xlbm, nbbm);
  1658 + Map<String, Object> m=new HashMap<String,Object>();
  1659 + List<Ylb> list_=new ArrayList<Ylb>();
  1660 + for (int i = 0; i < list.size(); i++) {
  1661 + Ylb t=list.get(i);
  1662 + if(m.get(t.getNbbm())==null){
  1663 + m.put(t.getNbbm(), t.getNbbm());
  1664 + list_.add(t);
  1665 + }
  1666 + }
  1667 + return list_;
1660 1668 }
1661 1669 }
... ...
src/main/java/com/bsth/service/realcontrol/impl/ScheduleRealInfoServiceImpl.java
... ... @@ -2532,7 +2532,11 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
2532 2532 map.put("ssgl_kx", culateService.culateCJLC(list, "客稀"));
2533 2533 map.put("ssgl_qh", culateService.culateCJLC(list, "气候"));
2534 2534 map.put("ssgl_yw", culateService.culateCJLC(list, "援外"));
2535   - map.put("ssgl_other", culateService.culateCJLC(list, "其他"));
  2535 + double ssgl_pc=culateService.culateCJLC(list, "配车");
  2536 + double ssgl_by=culateService.culateCJLC(list, "保养");
  2537 + double ssgl_cj=culateService.culateCJLC(list, "抽减");
  2538 + double ssgl_qt=culateService.culateCJLC(list, "其他");
  2539 + map.put("ssgl_other", Arith.add(Arith.add(ssgl_pc, ssgl_by),Arith.add(ssgl_cj, ssgl_qt)));
2536 2540 map.put("ssbc", culateService.culateLbbc(list));
2537 2541 map.put("ljgl", ljgl);
2538 2542 map.put("jhbc", culateService.culateJhbc(list,""));
... ... @@ -2648,7 +2652,12 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
2648 2652 map.put("ssgl_kx", culateService.culateCJLC(list, "客稀"));
2649 2653 map.put("ssgl_qh", culateService.culateCJLC(list, "气候"));
2650 2654 map.put("ssgl_yw", culateService.culateCJLC(list, "援外"));
2651   - map.put("ssgl_other", culateService.culateCJLC(list, "其他"));
  2655 + double ssgl_pc=culateService.culateCJLC(list, "配车");
  2656 + double ssgl_by=culateService.culateCJLC(list, "保养");
  2657 + double ssgl_cj=culateService.culateCJLC(list, "抽减");
  2658 + double ssgl_qt=culateService.culateCJLC(list, "其他");
  2659 + map.put("ssgl_other", Arith.add(Arith.add(ssgl_pc, ssgl_by),Arith.add(ssgl_cj, ssgl_qt)));
  2660 +
2652 2661 map.put("ssbc", culateService.culateLbbc(list));
2653 2662 map.put("ljgl", ljgl);
2654 2663 map.put("jhbc", culateService.culateJhbc(list,""));
... ... @@ -3391,7 +3400,6 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
3391 3400 boolean dest2 = sch.getStatus() == -1;
3392 3401 if (!dest1 && dest2) {
3393 3402 oldSch.destroy();
3394   - oldSch.setAdjustExps(sch.getAdjustExps());
3395 3403 aflog.log("烂班");
3396 3404 }
3397 3405 else if(dest1 && !dest2){
... ... @@ -3403,6 +3411,7 @@ public class ScheduleRealInfoServiceImpl extends BaseServiceImpl&lt;ScheduleRealInf
3403 3411 aflog.log("撤销烂班");
3404 3412 }
3405 3413  
  3414 + oldSch.setAdjustExps(sch.getAdjustExps());
3406 3415  
3407 3416 /**
3408 3417 * 修改班次里程
... ...
src/main/java/com/bsth/service/schedule/impl/PeopleCarPlanServiceImpl.java
... ... @@ -1924,13 +1924,11 @@ public class PeopleCarPlanServiceImpl implements PeopleCarPlanService {
1924 1924 }else{
1925 1925 sql_ += " and xl_bm = '"+line+"'";
1926 1926 }
1927   -
1928 1927  
1929   - String sql="SELECT r.id,r.schedule_date_str,r.xl_name,r.xl_bm,r.cl_zbh,r.j_gh,r.j_name,"
1930   - + " r.fcsj,d. TIMESTAMP,d.reply46,d.reply47,d.reply46time,d.reply47time,"
1931   - + " r.gs_name,r.fgs_name,CONCAT(r.xl_bm,'_',r.id) as line_sch FROM ("+sql_+") "
1932   - + " AS r LEFT JOIN bsth_v_directive_60 AS d ON r.id = d.sch AND d.is_dispatch = 1"
1933   - + " order by r.xl_name,r.id,d.timestamp desc ";
  1928 +
  1929 + String sql="SELECT r.id,r.schedule_date_str,r.xl_name,r.xl_bm,r.cl_zbh,r.j_gh,r.j_name,r.fcsj,"
  1930 + + " r.gs_name,r.fgs_name,CONCAT(r.xl_bm,'_',r.id) as line_sch FROM ("+sql_+") AS r"
  1931 + + " order by r.xl_name,r.id ";
1934 1932  
1935 1933 List<Map<String, Object>> list = jdbcTemplate.query(sql,
1936 1934 new RowMapper<Map<String, Object>>(){
... ... @@ -1945,17 +1943,59 @@ public class PeopleCarPlanServiceImpl implements PeopleCarPlanService {
1945 1943 map.put("jGh", rs.getString("j_gh"));
1946 1944 map.put("jName", rs.getString("j_name"));
1947 1945 map.put("fcsj", rs.getString("fcsj"));
1948   - map.put("timestamp", rs.getString("timestamp"));
  1946 + map.put("company", rs.getObject("gs_name"));
  1947 + map.put("subCompany", rs.getObject("fgs_name"));
  1948 + map.put("lineSch", rs.getString("line_sch"));
  1949 + return map;
  1950 + }
  1951 + });
  1952 +
  1953 +
  1954 + Date dateTime = new Date();
  1955 + try {
  1956 + dateTime = new SimpleDateFormat("yyyy-MM-dd").parse(date);
  1957 + } catch (ParseException e) {
  1958 + // TODO Auto-generated catch block
  1959 + e.printStackTrace();
  1960 + }
  1961 +
  1962 + sql="SELECT sch,TIMESTAMP,reply46,reply47,reply46time,reply47time"
  1963 + + " FROM bsth_v_directive_60 WHERE is_dispatch = 1 AND sch is not null"
  1964 + + " AND TIMESTAMP >= "+(dateTime.getTime())
  1965 + + " AND TIMESTAMP < "+(dateTime.getTime() + 1000*60*60*24);
  1966 +
  1967 + List<Map<String, Object>> list2 = jdbcTemplate.query(sql,
  1968 + new RowMapper<Map<String, Object>>(){
  1969 + @Override
  1970 + public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
  1971 + Map<String, Object> map = new HashMap<String, Object>();
  1972 + map.put("sch", rs.getString("sch"));
  1973 + map.put("TIMESTAMP", rs.getString("TIMESTAMP"));
1949 1974 map.put("reply46", rs.getString("reply46"));
1950 1975 map.put("reply47", rs.getString("reply47"));
1951 1976 map.put("reply46time", rs.getObject("reply46time"));
1952 1977 map.put("reply47time", rs.getObject("reply47time"));
1953   - map.put("company", rs.getObject("gs_name"));
1954   - map.put("subCompany", rs.getObject("fgs_name"));
1955   - map.put("lineSch", rs.getString("line_sch"));
  1978 +
1956 1979 return map;
1957 1980 }
1958 1981 });
  1982 +
  1983 + Map<String, Map<String, Object>> keyMap = new HashMap<String, Map<String,Object>>();
  1984 + for(Map<String, Object> m : list2){
  1985 + keyMap.put(m.get("sch").toString(), m);
  1986 + }
  1987 + for(Map<String, Object> m : list){
  1988 + String id = m.get("id").toString();
  1989 + if(keyMap.containsKey(id)){
  1990 + Map<String, Object> map2 = keyMap.get(id);
  1991 + m.put("TIMESTAMP", map2.get("TIMESTAMP"));
  1992 + m.put("reply46", map2.get("reply46"));
  1993 + m.put("reply47", map2.get("reply47"));
  1994 + m.put("reply46time", map2.get("reply46time"));
  1995 + m.put("reply47time", map2.get("reply47time"));
  1996 + }
  1997 + }
  1998 +
1959 1999 List<Map<String, Object>> list_=new ArrayList<Map<String,Object>>();
1960 2000 int jhs = 0,sjs=0,wqr=0;
1961 2001 Map<String, Object> m_;
... ... @@ -2063,15 +2103,11 @@ public class PeopleCarPlanServiceImpl implements PeopleCarPlanService {
2063 2103 String type = map.get("type").toString();
2064 2104  
2065 2105 String sql_="select * from bsth_c_s_sp_info_real "
2066   - + " WHERE schedule_date_str = '"+date+"' and xl_bm = '"+line+"'";
  2106 + + " WHERE schedule_date_str = '"+date+"' and xl_bm = '"+line+"'";
2067 2107  
2068   -
2069   - String sql="SELECT r.id,r.schedule_date_str,r.xl_name,r.xl_bm,r.cl_zbh,r.j_gh,r.j_name,"
2070   - + " r.fcsj,d. TIMESTAMP,d.reply46,d.reply47,d.reply46time,d.reply47time,"
2071   - + " r.gs_name,r.fgs_name,CONCAT(r.j_gh,'_',r.id) as gh_sch FROM ("+sql_+") "
2072   - + " AS r LEFT JOIN bsth_v_directive_60 AS d ON r.id = d.sch AND d.is_dispatch = 1"
2073   - + " order by r.j_gh,r.cl_zbh,r.id,d.timestamp desc ";
2074   -
  2108 + String sql="SELECT r.id,r.schedule_date_str,r.xl_name,r.xl_bm,r.cl_zbh,r.j_gh,r.j_name,r.fcsj,"
  2109 + + " r.gs_name,r.fgs_name,CONCAT(r.xl_bm,'_',r.id) as gh_sch FROM ("+sql_+") AS r"
  2110 + + " order by r.xl_name,r.id ";
2075 2111  
2076 2112 List<Map<String, Object>> list = jdbcTemplate.query(sql,
2077 2113 new RowMapper<Map<String, Object>>(){
... ... @@ -2086,17 +2122,58 @@ public class PeopleCarPlanServiceImpl implements PeopleCarPlanService {
2086 2122 map.put("jGh", rs.getString("j_gh"));
2087 2123 map.put("jName", rs.getString("j_name"));
2088 2124 map.put("fcsj", rs.getString("fcsj"));
2089   - map.put("timestamp", rs.getString("timestamp"));
  2125 + map.put("company", rs.getObject("gs_name"));
  2126 + map.put("subCompany", rs.getObject("fgs_name"));
  2127 + map.put("ghSch", rs.getString("gh_sch"));
  2128 + return map;
  2129 + }
  2130 + });
  2131 +
  2132 +
  2133 + Date dateTime = new Date();
  2134 + try {
  2135 + dateTime = new SimpleDateFormat("yyyy-MM-dd").parse(date);
  2136 + } catch (ParseException e) {
  2137 + // TODO Auto-generated catch block
  2138 + e.printStackTrace();
  2139 + }
  2140 +
  2141 + sql="SELECT sch,TIMESTAMP,reply46,reply47,reply46time,reply47time"
  2142 + + " FROM bsth_v_directive_60 WHERE is_dispatch = 1 AND sch is not null"
  2143 + + " AND TIMESTAMP >= "+(dateTime.getTime())
  2144 + + " AND TIMESTAMP < "+(dateTime.getTime() + 1000*60*60*24);
  2145 +
  2146 + List<Map<String, Object>> list2 = jdbcTemplate.query(sql,
  2147 + new RowMapper<Map<String, Object>>(){
  2148 + @Override
  2149 + public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
  2150 + Map<String, Object> map = new HashMap<String, Object>();
  2151 + map.put("sch", rs.getString("sch"));
  2152 + map.put("TIMESTAMP", rs.getString("TIMESTAMP"));
2090 2153 map.put("reply46", rs.getString("reply46"));
2091 2154 map.put("reply47", rs.getString("reply47"));
2092 2155 map.put("reply46time", rs.getObject("reply46time"));
2093 2156 map.put("reply47time", rs.getObject("reply47time"));
2094   - map.put("company", rs.getObject("gs_name"));
2095   - map.put("subCompany", rs.getObject("fgs_name"));
2096   - map.put("ghSch", rs.getString("gh_sch"));
  2157 +
2097 2158 return map;
2098 2159 }
2099 2160 });
  2161 +
  2162 + Map<String, Map<String, Object>> keyMap = new HashMap<String, Map<String,Object>>();
  2163 + for(Map<String, Object> m : list2){
  2164 + keyMap.put(m.get("sch").toString(), m);
  2165 + }
  2166 + for(Map<String, Object> m : list){
  2167 + String id = m.get("id").toString();
  2168 + if(keyMap.containsKey(id)){
  2169 + Map<String, Object> map2 = keyMap.get(id);
  2170 + m.put("TIMESTAMP", map2.get("TIMESTAMP"));
  2171 + m.put("reply46", map2.get("reply46"));
  2172 + m.put("reply47", map2.get("reply47"));
  2173 + m.put("reply46time", map2.get("reply46time"));
  2174 + m.put("reply47time", map2.get("reply47time"));
  2175 + }
  2176 + }
2100 2177  
2101 2178 List<Map<String, Object>> list_=new ArrayList<Map<String,Object>>();
2102 2179 int jhs = 0,sjs=0,wqr=0;
... ...
src/main/java/com/bsth/websocket/entity/WsScheduleRealInfo.java
1   -package com.bsth.websocket.entity;
2   -
3   -import com.bsth.entity.realcontrol.ChildTaskPlan;
4   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
5   -
6   -import javax.persistence.FetchType;
7   -import javax.persistence.OneToMany;
8   -import javax.persistence.Transient;
9   -import java.util.ArrayList;
10   -import java.util.HashSet;
11   -import java.util.List;
12   -import java.util.Set;
13   -
14   -/**
15   - * 精简字段的实际排班 entity
16   - * webSocket 传输用,去掉了页面不需要的一些字段
17   - * Created by panzhao on 2017/11/14.
18   - */
19   -public class WsScheduleRealInfo {
20   -
21   - public static WsScheduleRealInfo getInstance(ScheduleRealInfo sch){
22   - WsScheduleRealInfo wss = new WsScheduleRealInfo();
23   - wss.id = sch.getId();
24   - wss.scheduleDateStr = sch.getScheduleDateStr();
25   - wss.realExecDate = sch.getRealExecDate();
26   - wss.xlName = sch.getXlName();
27   - wss.xlBm = sch.getXlBm();
28   - wss.lpName = sch.getLpName();
29   - wss.clZbh = sch.getClZbh();
30   - wss.jGh = sch.getjGh();
31   - wss.jName = sch.getjName();
32   - wss.sGh = sch.getsGh();
33   - wss.sName = sch.getsName();
34   - wss.xlDir = sch.getXlDir();
35   - wss.qdzCode = sch.getQdzCode();
36   - wss.qdzName = sch.getQdzName();
37   - wss.zdzCode = sch.getZdzCode();
38   - wss.zdzName = sch.getZdzName();
39   - wss.fcsj = sch.getFcsj();
40   - wss.fcsjT = sch.getFcsjT();
41   - wss.zdsj = sch.getZdsj();
42   - wss.zdsjT = sch.getZdsjT();
43   - wss.jhlc = sch.getJhlc();
44   - wss.jhlcOrig = sch.getJhlcOrig();
45   - wss.bcsj = sch.getBcsj();
46   - wss.bcType = sch.getBcType();
47   - wss.majorStationName = sch.getMajorStationName();
48   - wss.fcsjActual = sch.getFcsjActual();
49   - wss.fcsjActualTime = sch.getFcsjActualTime();
50   - wss.zdsjActual = sch.getZdsjActual();
51   - wss.zdsjActualTime = sch.getZdsjActualTime();
52   - wss.status = sch.getStatus();
53   - wss.adjustExps = sch.getAdjustExps();
54   - wss.sflj = sch.isSflj();
55   - wss.late = sch.isLate();
56   - wss.late2 = sch.isLate2();
57   - wss.lateMinute = sch.getLateMinute();
58   - wss.remarks = sch.getRemarks();
59   - wss.dfsj = sch.getDfsj();
60   - wss.dfsjT = sch.getDfsjT();
61   - wss.directiveState = sch.getDirectiveState();
62   - wss.qdzArrDatejh = sch.getQdzArrDatejh();
63   - wss.qdzArrDatesj = sch.getQdzArrDatesj();
64   - wss.cTasks = sch.getcTasks();
65   - wss.gsName = sch.getGsName();
66   - wss.gsBm = sch.getGsBm();
67   - wss.fgsName = sch.getFgsName();
68   - wss.fgsBm = sch.getFgsBm();
69   - wss.dfAuto = sch.isDfAuto();
70   - wss.online = sch.isOnline();
71   - wss.reissue = sch.isReissue();
72   - wss.driftStatus = sch.getDriftStatus();
73   - wss.ccService = sch.isCcService();
74   - return wss;
75   - }
76   -
77   -
78   - public static List<WsScheduleRealInfo> getMultiInstance(List<ScheduleRealInfo> list){
79   - List<WsScheduleRealInfo> rs = new ArrayList<>();
80   - for(ScheduleRealInfo sch : list){
81   - rs.add(getInstance(sch));
82   - }
83   - return rs;
84   - }
85   -
86   - /** 主键Id */
87   - private Long id;
88   -
89   - /** 排班日期字符串 YYYY-MM-DD */
90   - private String scheduleDateStr;
91   -
92   - /** 真实执行时间 yyyy-MM-dd */
93   - private String realExecDate;
94   -
95   - /** 线路名称 */
96   - private String xlName;
97   - /** 线路编码 */
98   - private String xlBm;
99   -
100   - /** 路牌名称 */
101   - private String lpName;
102   -
103   - /** 车辆自编号 */
104   - private String clZbh;
105   -
106   - /** 驾驶员工号 */
107   - private String jGh;
108   - /** 驾驶员名字 */
109   - private String jName;
110   - /** 售票员工号 */
111   - private String sGh;
112   - /** 售票员名字 */
113   - private String sName;
114   -
115   - /** 线路方向 */
116   - private String xlDir;
117   - /** 起点站code*/
118   - private String qdzCode;
119   - /** 起点站名字 */
120   - private String qdzName;
121   -
122   - /** 终点站code*/
123   - private String zdzCode;
124   - /** 终点站名字 */
125   - private String zdzName;
126   -
127   - /** 计划发车时间(格式 HH:mm) */
128   - private String fcsj;
129   - /** 计划发车时间戳*/
130   - @Transient
131   - private Long fcsjT;
132   -
133   - /** 计划终点时间(格式 HH:mm) */
134   - private String zdsj;
135   - /** 计划终点时间戳*/
136   - @Transient
137   - private Long zdsjT;
138   -
139   - /** 计划里程 */
140   - private Double jhlc;
141   -
142   - /** 原始计划里程 (原计调的数据) */
143   - private Double jhlcOrig;
144   - /** 班次历时 */
145   - private Integer bcsj;
146   -
147   - /**
148   - * 班次类型 TODO:正常班次、出场、进场、加油、区间班次、放空班次、放大站班次、两点间空驶
149   - */
150   - private String bcType;
151   -
152   - //放站班次 站点名称
153   - private String majorStationName;
154   -
155   - /** 实际发车时间*/
156   - private String fcsjActual;
157   - /** 实际发车时间戳*/
158   - @Transient
159   - private Long fcsjActualTime;
160   - /**实际终点时间 */
161   - private String zdsjActual;
162   - /** 实际终点时间戳*/
163   - @Transient
164   - private Long zdsjActualTime;
165   -
166   - /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */
167   - private int status;
168   -
169   - private String adjustExps;
170   -
171   - /** 是否是临加班次 */
172   - private boolean sflj;
173   -
174   - /** 是否误点 (应发未发)*/
175   - @Transient
176   - private boolean late;
177   -
178   - /** 是否误点 (应发未到) */
179   - @Transient
180   - private boolean late2;
181   - /** 误点停靠时间 */
182   - @Transient
183   - private float lateMinute;
184   -
185   - /** 备注*/
186   - private String remarks;
187   -
188   - /**待发时间(格式 HH:mm) */
189   - private String dfsj;
190   -
191   - /**待发时间戳 */
192   - @Transient
193   - private Long dfsjT;
194   -
195   - /** 指令下发状态 60: 已发送, 100: 设备确认收到, 200:驾驶员确认 0:失败 */
196   - private Integer directiveState = -1;
197   -
198   - /** 起点站计划到达时间 */
199   - @Transient
200   - private String qdzArrDatejh;
201   -
202   - /** 起点站实际到达时间 */
203   - @Transient
204   - private String qdzArrDatesj;
205   -
206   - /** 子任务 */
207   - @OneToMany(fetch = FetchType.LAZY, mappedBy = "schedule")
208   - private Set<ChildTaskPlan> cTasks = new HashSet<>();
209   -
210   - /** 关联的公司名称 */
211   - private String gsName;
212   - /** 关联的公司编码 */
213   - private String gsBm;
214   - /** 关联的分公司名称 */
215   - private String fgsName;
216   - /** 关联的分公司编码 */
217   - private String fgsBm;
218   -
219   - //待发调试(是否自动调整)
220   - private boolean dfAuto;
221   - //是否有GPS信号
222   - private boolean online;
223   -
224   - /** 是否有补发GPS信号 */
225   - private boolean reissue;
226   -
227   - /**
228   - * 漂移状态
229   - * 1: 发车漂移
230   - * 2:到站漂移
231   - * 3:中途漂移
232   - */
233   - private Integer driftStatus = 0;
234   -
235   - /**
236   - * 换车营运标记 true 表示该主任务由 【中途换车子任务】 级联生成
237   - */
238   - private boolean ccService;
239   -
240   - public Long getId() {
241   - return id;
242   - }
243   -
244   - public void setId(Long id) {
245   - this.id = id;
246   - }
247   -
248   - public String getScheduleDateStr() {
249   - return scheduleDateStr;
250   - }
251   -
252   - public void setScheduleDateStr(String scheduleDateStr) {
253   - this.scheduleDateStr = scheduleDateStr;
254   - }
255   -
256   - public String getRealExecDate() {
257   - return realExecDate;
258   - }
259   -
260   - public void setRealExecDate(String realExecDate) {
261   - this.realExecDate = realExecDate;
262   - }
263   -
264   - public String getXlName() {
265   - return xlName;
266   - }
267   -
268   - public void setXlName(String xlName) {
269   - this.xlName = xlName;
270   - }
271   -
272   - public String getXlBm() {
273   - return xlBm;
274   - }
275   -
276   - public void setXlBm(String xlBm) {
277   - this.xlBm = xlBm;
278   - }
279   -
280   - public String getLpName() {
281   - return lpName;
282   - }
283   -
284   - public void setLpName(String lpName) {
285   - this.lpName = lpName;
286   - }
287   -
288   - public String getClZbh() {
289   - return clZbh;
290   - }
291   -
292   - public void setClZbh(String clZbh) {
293   - this.clZbh = clZbh;
294   - }
295   -
296   - public String getjGh() {
297   - return jGh;
298   - }
299   -
300   - public void setjGh(String jGh) {
301   - this.jGh = jGh;
302   - }
303   -
304   - public String getjName() {
305   - return jName;
306   - }
307   -
308   - public void setjName(String jName) {
309   - this.jName = jName;
310   - }
311   -
312   - public String getsGh() {
313   - return sGh;
314   - }
315   -
316   - public void setsGh(String sGh) {
317   - this.sGh = sGh;
318   - }
319   -
320   - public String getsName() {
321   - return sName;
322   - }
323   -
324   - public void setsName(String sName) {
325   - this.sName = sName;
326   - }
327   -
328   - public String getXlDir() {
329   - return xlDir;
330   - }
331   -
332   - public void setXlDir(String xlDir) {
333   - this.xlDir = xlDir;
334   - }
335   -
336   - public String getQdzCode() {
337   - return qdzCode;
338   - }
339   -
340   - public void setQdzCode(String qdzCode) {
341   - this.qdzCode = qdzCode;
342   - }
343   -
344   - public String getQdzName() {
345   - return qdzName;
346   - }
347   -
348   - public void setQdzName(String qdzName) {
349   - this.qdzName = qdzName;
350   - }
351   -
352   - public String getZdzCode() {
353   - return zdzCode;
354   - }
355   -
356   - public void setZdzCode(String zdzCode) {
357   - this.zdzCode = zdzCode;
358   - }
359   -
360   - public String getZdzName() {
361   - return zdzName;
362   - }
363   -
364   - public void setZdzName(String zdzName) {
365   - this.zdzName = zdzName;
366   - }
367   -
368   - public String getFcsj() {
369   - return fcsj;
370   - }
371   -
372   - public void setFcsj(String fcsj) {
373   - this.fcsj = fcsj;
374   - }
375   -
376   - public Long getFcsjT() {
377   - return fcsjT;
378   - }
379   -
380   - public void setFcsjT(Long fcsjT) {
381   - this.fcsjT = fcsjT;
382   - }
383   -
384   - public String getZdsj() {
385   - return zdsj;
386   - }
387   -
388   - public void setZdsj(String zdsj) {
389   - this.zdsj = zdsj;
390   - }
391   -
392   - public Long getZdsjT() {
393   - return zdsjT;
394   - }
395   -
396   - public void setZdsjT(Long zdsjT) {
397   - this.zdsjT = zdsjT;
398   - }
399   -
400   - public Double getJhlc() {
401   - return jhlc;
402   - }
403   -
404   - public void setJhlc(Double jhlc) {
405   - this.jhlc = jhlc;
406   - }
407   -
408   - public Double getJhlcOrig() {
409   - return jhlcOrig;
410   - }
411   -
412   - public void setJhlcOrig(Double jhlcOrig) {
413   - this.jhlcOrig = jhlcOrig;
414   - }
415   -
416   - public Integer getBcsj() {
417   - return bcsj;
418   - }
419   -
420   - public void setBcsj(Integer bcsj) {
421   - this.bcsj = bcsj;
422   - }
423   -
424   - public String getBcType() {
425   - return bcType;
426   - }
427   -
428   - public void setBcType(String bcType) {
429   - this.bcType = bcType;
430   - }
431   -
432   - public String getMajorStationName() {
433   - return majorStationName;
434   - }
435   -
436   - public void setMajorStationName(String majorStationName) {
437   - this.majorStationName = majorStationName;
438   - }
439   -
440   - public String getFcsjActual() {
441   - return fcsjActual;
442   - }
443   -
444   - public void setFcsjActual(String fcsjActual) {
445   - this.fcsjActual = fcsjActual;
446   - }
447   -
448   - public Long getFcsjActualTime() {
449   - return fcsjActualTime;
450   - }
451   -
452   - public void setFcsjActualTime(Long fcsjActualTime) {
453   - this.fcsjActualTime = fcsjActualTime;
454   - }
455   -
456   - public String getZdsjActual() {
457   - return zdsjActual;
458   - }
459   -
460   - public void setZdsjActual(String zdsjActual) {
461   - this.zdsjActual = zdsjActual;
462   - }
463   -
464   - public Long getZdsjActualTime() {
465   - return zdsjActualTime;
466   - }
467   -
468   - public void setZdsjActualTime(Long zdsjActualTime) {
469   - this.zdsjActualTime = zdsjActualTime;
470   - }
471   -
472   - public int getStatus() {
473   - return status;
474   - }
475   -
476   - public void setStatus(int status) {
477   - this.status = status;
478   - }
479   -
480   - public String getAdjustExps() {
481   - return adjustExps;
482   - }
483   -
484   - public void setAdjustExps(String adjustExps) {
485   - this.adjustExps = adjustExps;
486   - }
487   -
488   - public boolean isSflj() {
489   - return sflj;
490   - }
491   -
492   - public void setSflj(boolean sflj) {
493   - this.sflj = sflj;
494   - }
495   -
496   - public boolean isLate() {
497   - return late;
498   - }
499   -
500   - public void setLate(boolean late) {
501   - this.late = late;
502   - }
503   -
504   - public boolean isLate2() {
505   - return late2;
506   - }
507   -
508   - public void setLate2(boolean late2) {
509   - this.late2 = late2;
510   - }
511   -
512   - public float getLateMinute() {
513   - return lateMinute;
514   - }
515   -
516   - public void setLateMinute(float lateMinute) {
517   - this.lateMinute = lateMinute;
518   - }
519   -
520   - public String getRemarks() {
521   - return remarks;
522   - }
523   -
524   - public void setRemarks(String remarks) {
525   - this.remarks = remarks;
526   - }
527   -
528   - public String getDfsj() {
529   - return dfsj;
530   - }
531   -
532   - public void setDfsj(String dfsj) {
533   - this.dfsj = dfsj;
534   - }
535   -
536   - public Long getDfsjT() {
537   - return dfsjT;
538   - }
539   -
540   - public void setDfsjT(Long dfsjT) {
541   - this.dfsjT = dfsjT;
542   - }
543   -
544   - public Integer getDirectiveState() {
545   - return directiveState;
546   - }
547   -
548   - public void setDirectiveState(Integer directiveState) {
549   - this.directiveState = directiveState;
550   - }
551   -
552   - public String getQdzArrDatejh() {
553   - return qdzArrDatejh;
554   - }
555   -
556   - public void setQdzArrDatejh(String qdzArrDatejh) {
557   - this.qdzArrDatejh = qdzArrDatejh;
558   - }
559   -
560   - public String getQdzArrDatesj() {
561   - return qdzArrDatesj;
562   - }
563   -
564   - public void setQdzArrDatesj(String qdzArrDatesj) {
565   - this.qdzArrDatesj = qdzArrDatesj;
566   - }
567   -
568   - public Set<ChildTaskPlan> getcTasks() {
569   - return cTasks;
570   - }
571   -
572   - public void setcTasks(Set<ChildTaskPlan> cTasks) {
573   - this.cTasks = cTasks;
574   - }
575   -
576   - public String getGsName() {
577   - return gsName;
578   - }
579   -
580   - public void setGsName(String gsName) {
581   - this.gsName = gsName;
582   - }
583   -
584   - public String getGsBm() {
585   - return gsBm;
586   - }
587   -
588   - public void setGsBm(String gsBm) {
589   - this.gsBm = gsBm;
590   - }
591   -
592   - public String getFgsName() {
593   - return fgsName;
594   - }
595   -
596   - public void setFgsName(String fgsName) {
597   - this.fgsName = fgsName;
598   - }
599   -
600   - public String getFgsBm() {
601   - return fgsBm;
602   - }
603   -
604   - public void setFgsBm(String fgsBm) {
605   - this.fgsBm = fgsBm;
606   - }
607   -
608   - public boolean isDfAuto() {
609   - return dfAuto;
610   - }
611   -
612   - public void setDfAuto(boolean dfAuto) {
613   - this.dfAuto = dfAuto;
614   - }
615   -
616   - public boolean isOnline() {
617   - return online;
618   - }
619   -
620   - public void setOnline(boolean online) {
621   - this.online = online;
622   - }
623   -
624   - public boolean isReissue() {
625   - return reissue;
626   - }
627   -
628   - public void setReissue(boolean reissue) {
629   - this.reissue = reissue;
630   - }
631   -
632   - public Integer getDriftStatus() {
633   - return driftStatus;
634   - }
635   -
636   - public void setDriftStatus(Integer driftStatus) {
637   - this.driftStatus = driftStatus;
638   - }
639   -
640   - public boolean isCcService() {
641   - return ccService;
642   - }
643   -
644   - public void setCcService(boolean ccService) {
645   - this.ccService = ccService;
646   - }
647   -}
  1 +package com.bsth.websocket.entity;
  2 +
  3 +import com.bsth.entity.realcontrol.ChildTaskPlan;
  4 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  5 +
  6 +import javax.persistence.FetchType;
  7 +import javax.persistence.OneToMany;
  8 +import javax.persistence.Transient;
  9 +import java.util.ArrayList;
  10 +import java.util.HashSet;
  11 +import java.util.List;
  12 +import java.util.Set;
  13 +
  14 +/**
  15 + * 精简字段的实际排班 entity
  16 + * webSocket 传输用,去掉了页面不需要的一些字段
  17 + * Created by panzhao on 2017/11/14.
  18 + */
  19 +public class WsScheduleRealInfo {
  20 +
  21 + public static WsScheduleRealInfo getInstance(ScheduleRealInfo sch){
  22 + if(null == sch)
  23 + return null;
  24 + WsScheduleRealInfo wss = new WsScheduleRealInfo();
  25 + wss.id = sch.getId();
  26 + wss.scheduleDateStr = sch.getScheduleDateStr();
  27 + wss.realExecDate = sch.getRealExecDate();
  28 + wss.xlName = sch.getXlName();
  29 + wss.xlBm = sch.getXlBm();
  30 + wss.lpName = sch.getLpName();
  31 + wss.clZbh = sch.getClZbh();
  32 + wss.jGh = sch.getjGh();
  33 + wss.jName = sch.getjName();
  34 + wss.sGh = sch.getsGh();
  35 + wss.sName = sch.getsName();
  36 + wss.xlDir = sch.getXlDir();
  37 + wss.qdzCode = sch.getQdzCode();
  38 + wss.qdzName = sch.getQdzName();
  39 + wss.zdzCode = sch.getZdzCode();
  40 + wss.zdzName = sch.getZdzName();
  41 + wss.fcsj = sch.getFcsj();
  42 + wss.fcsjT = sch.getFcsjT();
  43 + wss.zdsj = sch.getZdsj();
  44 + wss.zdsjT = sch.getZdsjT();
  45 + wss.jhlc = sch.getJhlc();
  46 + wss.jhlcOrig = sch.getJhlcOrig();
  47 + wss.bcsj = sch.getBcsj();
  48 + wss.bcType = sch.getBcType();
  49 + wss.majorStationName = sch.getMajorStationName();
  50 + wss.fcsjActual = sch.getFcsjActual();
  51 + wss.fcsjActualTime = sch.getFcsjActualTime();
  52 + wss.zdsjActual = sch.getZdsjActual();
  53 + wss.zdsjActualTime = sch.getZdsjActualTime();
  54 + wss.status = sch.getStatus();
  55 + wss.adjustExps = sch.getAdjustExps();
  56 + wss.sflj = sch.isSflj();
  57 + wss.late = sch.isLate();
  58 + wss.late2 = sch.isLate2();
  59 + wss.lateMinute = sch.getLateMinute();
  60 + wss.remarks = sch.getRemarks();
  61 + wss.dfsj = sch.getDfsj();
  62 + wss.dfsjT = sch.getDfsjT();
  63 + wss.directiveState = sch.getDirectiveState();
  64 + wss.qdzArrDatejh = sch.getQdzArrDatejh();
  65 + wss.qdzArrDatesj = sch.getQdzArrDatesj();
  66 + wss.cTasks = sch.getcTasks();
  67 + wss.gsName = sch.getGsName();
  68 + wss.gsBm = sch.getGsBm();
  69 + wss.fgsName = sch.getFgsName();
  70 + wss.fgsBm = sch.getFgsBm();
  71 + wss.dfAuto = sch.isDfAuto();
  72 + wss.online = sch.isOnline();
  73 + wss.reissue = sch.isReissue();
  74 + wss.driftStatus = sch.getDriftStatus();
  75 + wss.ccService = sch.isCcService();
  76 + return wss;
  77 + }
  78 +
  79 +
  80 + public static List<WsScheduleRealInfo> getMultiInstance(List<ScheduleRealInfo> list){
  81 + List<WsScheduleRealInfo> rs = new ArrayList<>();
  82 + for(ScheduleRealInfo sch : list){
  83 + rs.add(getInstance(sch));
  84 + }
  85 + return rs;
  86 + }
  87 +
  88 + /** 主键Id */
  89 + private Long id;
  90 +
  91 + /** 排班日期字符串 YYYY-MM-DD */
  92 + private String scheduleDateStr;
  93 +
  94 + /** 真实执行时间 yyyy-MM-dd */
  95 + private String realExecDate;
  96 +
  97 + /** 线路名称 */
  98 + private String xlName;
  99 + /** 线路编码 */
  100 + private String xlBm;
  101 +
  102 + /** 路牌名称 */
  103 + private String lpName;
  104 +
  105 + /** 车辆自编号 */
  106 + private String clZbh;
  107 +
  108 + /** 驾驶员工号 */
  109 + private String jGh;
  110 + /** 驾驶员名字 */
  111 + private String jName;
  112 + /** 售票员工号 */
  113 + private String sGh;
  114 + /** 售票员名字 */
  115 + private String sName;
  116 +
  117 + /** 线路方向 */
  118 + private String xlDir;
  119 + /** 起点站code*/
  120 + private String qdzCode;
  121 + /** 起点站名字 */
  122 + private String qdzName;
  123 +
  124 + /** 终点站code*/
  125 + private String zdzCode;
  126 + /** 终点站名字 */
  127 + private String zdzName;
  128 +
  129 + /** 计划发车时间(格式 HH:mm) */
  130 + private String fcsj;
  131 + /** 计划发车时间戳*/
  132 + @Transient
  133 + private Long fcsjT;
  134 +
  135 + /** 计划终点时间(格式 HH:mm) */
  136 + private String zdsj;
  137 + /** 计划终点时间戳*/
  138 + @Transient
  139 + private Long zdsjT;
  140 +
  141 + /** 计划里程 */
  142 + private Double jhlc;
  143 +
  144 + /** 原始计划里程 (原计调的数据) */
  145 + private Double jhlcOrig;
  146 + /** 班次历时 */
  147 + private Integer bcsj;
  148 +
  149 + /**
  150 + * 班次类型 TODO:正常班次、出场、进场、加油、区间班次、放空班次、放大站班次、两点间空驶
  151 + */
  152 + private String bcType;
  153 +
  154 + //放站班次 站点名称
  155 + private String majorStationName;
  156 +
  157 + /** 实际发车时间*/
  158 + private String fcsjActual;
  159 + /** 实际发车时间戳*/
  160 + @Transient
  161 + private Long fcsjActualTime;
  162 + /**实际终点时间 */
  163 + private String zdsjActual;
  164 + /** 实际终点时间戳*/
  165 + @Transient
  166 + private Long zdsjActualTime;
  167 +
  168 + /**班次状态 0 未执行 1 正在执行 2 已执行 -1 已烂班 */
  169 + private int status;
  170 +
  171 + private String adjustExps;
  172 +
  173 + /** 是否是临加班次 */
  174 + private boolean sflj;
  175 +
  176 + /** 是否误点 (应发未发)*/
  177 + @Transient
  178 + private boolean late;
  179 +
  180 + /** 是否误点 (应发未到) */
  181 + @Transient
  182 + private boolean late2;
  183 + /** 误点停靠时间 */
  184 + @Transient
  185 + private float lateMinute;
  186 +
  187 + /** 备注*/
  188 + private String remarks;
  189 +
  190 + /**待发时间(格式 HH:mm) */
  191 + private String dfsj;
  192 +
  193 + /**待发时间戳 */
  194 + @Transient
  195 + private Long dfsjT;
  196 +
  197 + /** 指令下发状态 60: 已发送, 100: 设备确认收到, 200:驾驶员确认 0:失败 */
  198 + private Integer directiveState = -1;
  199 +
  200 + /** 起点站计划到达时间 */
  201 + @Transient
  202 + private String qdzArrDatejh;
  203 +
  204 + /** 起点站实际到达时间 */
  205 + @Transient
  206 + private String qdzArrDatesj;
  207 +
  208 + /** 子任务 */
  209 + @OneToMany(fetch = FetchType.LAZY, mappedBy = "schedule")
  210 + private Set<ChildTaskPlan> cTasks = new HashSet<>();
  211 +
  212 + /** 关联的公司名称 */
  213 + private String gsName;
  214 + /** 关联的公司编码 */
  215 + private String gsBm;
  216 + /** 关联的分公司名称 */
  217 + private String fgsName;
  218 + /** 关联的分公司编码 */
  219 + private String fgsBm;
  220 +
  221 + //待发调试(是否自动调整)
  222 + private boolean dfAuto;
  223 + //是否有GPS信号
  224 + private boolean online;
  225 +
  226 + /** 是否有补发GPS信号 */
  227 + private boolean reissue;
  228 +
  229 + /**
  230 + * 漂移状态
  231 + * 1: 发车漂移
  232 + * 2:到站漂移
  233 + * 3:中途漂移
  234 + */
  235 + private Integer driftStatus = 0;
  236 +
  237 + /**
  238 + * 换车营运标记 true 表示该主任务由 【中途换车子任务】 级联生成
  239 + */
  240 + private boolean ccService;
  241 +
  242 + public Long getId() {
  243 + return id;
  244 + }
  245 +
  246 + public void setId(Long id) {
  247 + this.id = id;
  248 + }
  249 +
  250 + public String getScheduleDateStr() {
  251 + return scheduleDateStr;
  252 + }
  253 +
  254 + public void setScheduleDateStr(String scheduleDateStr) {
  255 + this.scheduleDateStr = scheduleDateStr;
  256 + }
  257 +
  258 + public String getRealExecDate() {
  259 + return realExecDate;
  260 + }
  261 +
  262 + public void setRealExecDate(String realExecDate) {
  263 + this.realExecDate = realExecDate;
  264 + }
  265 +
  266 + public String getXlName() {
  267 + return xlName;
  268 + }
  269 +
  270 + public void setXlName(String xlName) {
  271 + this.xlName = xlName;
  272 + }
  273 +
  274 + public String getXlBm() {
  275 + return xlBm;
  276 + }
  277 +
  278 + public void setXlBm(String xlBm) {
  279 + this.xlBm = xlBm;
  280 + }
  281 +
  282 + public String getLpName() {
  283 + return lpName;
  284 + }
  285 +
  286 + public void setLpName(String lpName) {
  287 + this.lpName = lpName;
  288 + }
  289 +
  290 + public String getClZbh() {
  291 + return clZbh;
  292 + }
  293 +
  294 + public void setClZbh(String clZbh) {
  295 + this.clZbh = clZbh;
  296 + }
  297 +
  298 + public String getjGh() {
  299 + return jGh;
  300 + }
  301 +
  302 + public void setjGh(String jGh) {
  303 + this.jGh = jGh;
  304 + }
  305 +
  306 + public String getjName() {
  307 + return jName;
  308 + }
  309 +
  310 + public void setjName(String jName) {
  311 + this.jName = jName;
  312 + }
  313 +
  314 + public String getsGh() {
  315 + return sGh;
  316 + }
  317 +
  318 + public void setsGh(String sGh) {
  319 + this.sGh = sGh;
  320 + }
  321 +
  322 + public String getsName() {
  323 + return sName;
  324 + }
  325 +
  326 + public void setsName(String sName) {
  327 + this.sName = sName;
  328 + }
  329 +
  330 + public String getXlDir() {
  331 + return xlDir;
  332 + }
  333 +
  334 + public void setXlDir(String xlDir) {
  335 + this.xlDir = xlDir;
  336 + }
  337 +
  338 + public String getQdzCode() {
  339 + return qdzCode;
  340 + }
  341 +
  342 + public void setQdzCode(String qdzCode) {
  343 + this.qdzCode = qdzCode;
  344 + }
  345 +
  346 + public String getQdzName() {
  347 + return qdzName;
  348 + }
  349 +
  350 + public void setQdzName(String qdzName) {
  351 + this.qdzName = qdzName;
  352 + }
  353 +
  354 + public String getZdzCode() {
  355 + return zdzCode;
  356 + }
  357 +
  358 + public void setZdzCode(String zdzCode) {
  359 + this.zdzCode = zdzCode;
  360 + }
  361 +
  362 + public String getZdzName() {
  363 + return zdzName;
  364 + }
  365 +
  366 + public void setZdzName(String zdzName) {
  367 + this.zdzName = zdzName;
  368 + }
  369 +
  370 + public String getFcsj() {
  371 + return fcsj;
  372 + }
  373 +
  374 + public void setFcsj(String fcsj) {
  375 + this.fcsj = fcsj;
  376 + }
  377 +
  378 + public Long getFcsjT() {
  379 + return fcsjT;
  380 + }
  381 +
  382 + public void setFcsjT(Long fcsjT) {
  383 + this.fcsjT = fcsjT;
  384 + }
  385 +
  386 + public String getZdsj() {
  387 + return zdsj;
  388 + }
  389 +
  390 + public void setZdsj(String zdsj) {
  391 + this.zdsj = zdsj;
  392 + }
  393 +
  394 + public Long getZdsjT() {
  395 + return zdsjT;
  396 + }
  397 +
  398 + public void setZdsjT(Long zdsjT) {
  399 + this.zdsjT = zdsjT;
  400 + }
  401 +
  402 + public Double getJhlc() {
  403 + return jhlc;
  404 + }
  405 +
  406 + public void setJhlc(Double jhlc) {
  407 + this.jhlc = jhlc;
  408 + }
  409 +
  410 + public Double getJhlcOrig() {
  411 + return jhlcOrig;
  412 + }
  413 +
  414 + public void setJhlcOrig(Double jhlcOrig) {
  415 + this.jhlcOrig = jhlcOrig;
  416 + }
  417 +
  418 + public Integer getBcsj() {
  419 + return bcsj;
  420 + }
  421 +
  422 + public void setBcsj(Integer bcsj) {
  423 + this.bcsj = bcsj;
  424 + }
  425 +
  426 + public String getBcType() {
  427 + return bcType;
  428 + }
  429 +
  430 + public void setBcType(String bcType) {
  431 + this.bcType = bcType;
  432 + }
  433 +
  434 + public String getMajorStationName() {
  435 + return majorStationName;
  436 + }
  437 +
  438 + public void setMajorStationName(String majorStationName) {
  439 + this.majorStationName = majorStationName;
  440 + }
  441 +
  442 + public String getFcsjActual() {
  443 + return fcsjActual;
  444 + }
  445 +
  446 + public void setFcsjActual(String fcsjActual) {
  447 + this.fcsjActual = fcsjActual;
  448 + }
  449 +
  450 + public Long getFcsjActualTime() {
  451 + return fcsjActualTime;
  452 + }
  453 +
  454 + public void setFcsjActualTime(Long fcsjActualTime) {
  455 + this.fcsjActualTime = fcsjActualTime;
  456 + }
  457 +
  458 + public String getZdsjActual() {
  459 + return zdsjActual;
  460 + }
  461 +
  462 + public void setZdsjActual(String zdsjActual) {
  463 + this.zdsjActual = zdsjActual;
  464 + }
  465 +
  466 + public Long getZdsjActualTime() {
  467 + return zdsjActualTime;
  468 + }
  469 +
  470 + public void setZdsjActualTime(Long zdsjActualTime) {
  471 + this.zdsjActualTime = zdsjActualTime;
  472 + }
  473 +
  474 + public int getStatus() {
  475 + return status;
  476 + }
  477 +
  478 + public void setStatus(int status) {
  479 + this.status = status;
  480 + }
  481 +
  482 + public String getAdjustExps() {
  483 + return adjustExps;
  484 + }
  485 +
  486 + public void setAdjustExps(String adjustExps) {
  487 + this.adjustExps = adjustExps;
  488 + }
  489 +
  490 + public boolean isSflj() {
  491 + return sflj;
  492 + }
  493 +
  494 + public void setSflj(boolean sflj) {
  495 + this.sflj = sflj;
  496 + }
  497 +
  498 + public boolean isLate() {
  499 + return late;
  500 + }
  501 +
  502 + public void setLate(boolean late) {
  503 + this.late = late;
  504 + }
  505 +
  506 + public boolean isLate2() {
  507 + return late2;
  508 + }
  509 +
  510 + public void setLate2(boolean late2) {
  511 + this.late2 = late2;
  512 + }
  513 +
  514 + public float getLateMinute() {
  515 + return lateMinute;
  516 + }
  517 +
  518 + public void setLateMinute(float lateMinute) {
  519 + this.lateMinute = lateMinute;
  520 + }
  521 +
  522 + public String getRemarks() {
  523 + return remarks;
  524 + }
  525 +
  526 + public void setRemarks(String remarks) {
  527 + this.remarks = remarks;
  528 + }
  529 +
  530 + public String getDfsj() {
  531 + return dfsj;
  532 + }
  533 +
  534 + public void setDfsj(String dfsj) {
  535 + this.dfsj = dfsj;
  536 + }
  537 +
  538 + public Long getDfsjT() {
  539 + return dfsjT;
  540 + }
  541 +
  542 + public void setDfsjT(Long dfsjT) {
  543 + this.dfsjT = dfsjT;
  544 + }
  545 +
  546 + public Integer getDirectiveState() {
  547 + return directiveState;
  548 + }
  549 +
  550 + public void setDirectiveState(Integer directiveState) {
  551 + this.directiveState = directiveState;
  552 + }
  553 +
  554 + public String getQdzArrDatejh() {
  555 + return qdzArrDatejh;
  556 + }
  557 +
  558 + public void setQdzArrDatejh(String qdzArrDatejh) {
  559 + this.qdzArrDatejh = qdzArrDatejh;
  560 + }
  561 +
  562 + public String getQdzArrDatesj() {
  563 + return qdzArrDatesj;
  564 + }
  565 +
  566 + public void setQdzArrDatesj(String qdzArrDatesj) {
  567 + this.qdzArrDatesj = qdzArrDatesj;
  568 + }
  569 +
  570 + public Set<ChildTaskPlan> getcTasks() {
  571 + return cTasks;
  572 + }
  573 +
  574 + public void setcTasks(Set<ChildTaskPlan> cTasks) {
  575 + this.cTasks = cTasks;
  576 + }
  577 +
  578 + public String getGsName() {
  579 + return gsName;
  580 + }
  581 +
  582 + public void setGsName(String gsName) {
  583 + this.gsName = gsName;
  584 + }
  585 +
  586 + public String getGsBm() {
  587 + return gsBm;
  588 + }
  589 +
  590 + public void setGsBm(String gsBm) {
  591 + this.gsBm = gsBm;
  592 + }
  593 +
  594 + public String getFgsName() {
  595 + return fgsName;
  596 + }
  597 +
  598 + public void setFgsName(String fgsName) {
  599 + this.fgsName = fgsName;
  600 + }
  601 +
  602 + public String getFgsBm() {
  603 + return fgsBm;
  604 + }
  605 +
  606 + public void setFgsBm(String fgsBm) {
  607 + this.fgsBm = fgsBm;
  608 + }
  609 +
  610 + public boolean isDfAuto() {
  611 + return dfAuto;
  612 + }
  613 +
  614 + public void setDfAuto(boolean dfAuto) {
  615 + this.dfAuto = dfAuto;
  616 + }
  617 +
  618 + public boolean isOnline() {
  619 + return online;
  620 + }
  621 +
  622 + public void setOnline(boolean online) {
  623 + this.online = online;
  624 + }
  625 +
  626 + public boolean isReissue() {
  627 + return reissue;
  628 + }
  629 +
  630 + public void setReissue(boolean reissue) {
  631 + this.reissue = reissue;
  632 + }
  633 +
  634 + public Integer getDriftStatus() {
  635 + return driftStatus;
  636 + }
  637 +
  638 + public void setDriftStatus(Integer driftStatus) {
  639 + this.driftStatus = driftStatus;
  640 + }
  641 +
  642 + public boolean isCcService() {
  643 + return ccService;
  644 + }
  645 +
  646 + public void setCcService(boolean ccService) {
  647 + this.ccService = ccService;
  648 + }
  649 +}
... ...
src/main/resources/static/pages/base/line/js/line-list-table.js
... ... @@ -99,8 +99,10 @@
99 99 // 选择线路,填充线路编码搜索框
100 100 $("#lineSelect").on("change",function(){
101 101 var text = $('#lineSelect').val();
102   - var linecode = text.split("_");
103   - $("#lineCodeInput").val(linecode[2]);
  102 + if(text){
  103 + var linecode = text.split("_");
  104 + $("#lineCodeInput").val(linecode[2]);
  105 + }
104 106 });
105 107  
106 108 function gsdmTogsName(gsD,code) {
... ...
src/main/resources/static/pages/base/lineversions/js/lineversions-list-table.js
... ... @@ -89,8 +89,10 @@
89 89  
90 90 $('#lineSelect').on('change',function() {
91 91 var text = $('#lineSelect').val();
92   - var linecode = text.split("_");
93   - $("#lineCodeInput").val(linecode[2]);
  92 + if(text){
  93 + var linecode = text.split("_");
  94 + $("#lineCodeInput").val(linecode[2]);
  95 + }
94 96 });
95 97  
96 98 function gsdmTogsName(gsD,code) {
... ...
src/main/resources/static/pages/base/section/js/section-list-table.js
... ... @@ -165,8 +165,10 @@
165 165 $('#lineSelect').on('change',function() {
166 166 initldNameSelect();
167 167 var text = $('#lineSelect').val();
168   - var linecode = text.split("_");
169   - $("#lineCodeInput").val(linecode[2]);
  168 + if(text){
  169 + var linecode = text.split("_");
  170 + $("#lineCodeInput").val(linecode[2]);
  171 + }
170 172 });
171 173 $('#dirSelect').on('change',function() {
172 174 initldNameSelect();
... ...
src/main/resources/static/pages/base/station/js/station-list-table.js
... ... @@ -113,8 +113,10 @@
113 113 initzdNameSelect();
114 114 $('#destroy').val(0);
115 115 var text = $('#lineSelect').val();
116   - var linecode = text.split("_");
117   - $("#lineCodeInput").val(linecode[2]);
  116 + if(text){
  117 + var linecode = text.split("_");
  118 + $("#lineCodeInput").val(linecode[2]);
  119 + }
118 120 });
119 121  
120 122 $('#dirSelect').on('change',function() {
... ...
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalLpObj.js
1   -/**
2   - * 内部路牌对象。
3   - * @constructor
4   - */
5   -var InternalLpObj = function(
6   - orilpObj, // 原始路牌对象
7   - qCount, // 总共多少圈
8   - isUp // 圈是以上行开始还是下行开始
9   -) {
10   - // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
11   - this._$$_orign_lp_obj = orilpObj;
12   -
13   - this._$_isUp = isUp;
14   -
15   - // 路牌的圈数,注意每个路牌的圈数都是一致的,
16   - // 但并不是每一圈都有值
17   - // 第1圈从上标线开始
18   - // 第0圈表示中标线的第一个班次组成的半圈
19   - // 有多少圈根据最终迭代的结果来看
20   - this._$_qCount = qCount;
21   - // 保存的是 InternalGroupBcObj 对象
22   - this._$_groupBcArray = new Array(qCount);
23   -
24   - var i;
25   - for (i = 0; i < this._$_qCount; i++) {
26   - this._$_groupBcArray[i] = new InternalGroupObj(
27   - this, this._$_isUp, undefined, undefined);
28   - }
29   -
30   - // 距离上一个路牌的最小发车间隔时间
31   - // 用于纵向添加班次的时候使用
32   - // 默认第一个路牌为0
33   - this._$_minVerticalIntervalTime = 0;
34   -
35   - // 详细记录每圈每个方向上的发车间隔时间
36   - // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
37   - // 第一个方向是否上行由 _$_isUp 决定
38   - // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
39   - // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
40   - this._$_aVerticalIntervalTime = new Array(this._$_qCount);
41   - var i;
42   - for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
43   - this._$_aVerticalIntervalTime[i] = new Array(2);
44   - }
45   -
46   - // 班型的相关变量
47   - this._$_bx_isLb = false; // 是否连班
48   - this._$_bx_isfb = false; // 是否分班
49   - this._$_bx_isfb_5_2 = false; // 是否5休2分班
50   - this._$_bx_desc; // 班型描述(默认为路牌编号)
51   -
52   - // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
53   - this._$_other_bc_array = [];
54   -
55   - // TODO:
56   -
57   -};
58   -
59   -//------------------- get/set 方法 -------------------//
60   -
61   -InternalLpObj.prototype.getOtherBcArray = function() {
62   - return this._$_other_bc_array;
63   -};
64   -InternalLpObj.prototype.addOtherBcArray = function(ba) {
65   - this._$_other_bc_array = this._$_other_bc_array.concat(ba);
66   -};
67   -
68   -/**
69   - * 获取圈
70   - * @param qIndex 圈index
71   - */
72   -InternalLpObj.prototype.getGroup = function(qIndex) {
73   - return this._$_groupBcArray[qIndex];
74   -};
75   -
76   -/**
77   - * 获取班次。
78   - * @param qIndex 第几圈
79   - * @param bcIndex 第几个班次
80   - */
81   -InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
82   - var group = this._$_groupBcArray[qIndex];
83   - var bc;
84   - if (bcIndex == 0) {
85   - bc = group.getBc1();
86   - } else if (bcIndex == 1) {
87   - bc = group.getBc2();
88   - }
89   - return bc;
90   -};
91   -
92   -/**
93   - * 在具体位置设置班次。
94   - * @param qIndex 第几圈
95   - * @param bcIndex 第几个班次
96   - * @param bc 班次对象
97   - */
98   -InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
99   - var group = this._$_groupBcArray[qIndex];
100   - if (bcIndex == 0) {
101   - group.setBc1(bc);
102   - bc.setGroup(group);
103   - } else if (bcIndex == 1) {
104   - group.setBc2(bc);
105   - bc.setGroup(group);
106   - }
107   -};
108   -
109   -/**
110   - * 设置原始路牌对象。
111   - * @param lpObj 原始路牌对象
112   - */
113   -InternalLpObj.prototype.setLp = function(lpObj) {
114   - this._$$_orign_lp_obj = lpObj;
115   - var i;
116   - var group;
117   - for (i = 0; i < this._$_groupBcArray.length; i++) {
118   - group = this._$_groupBcArray[i];
119   - if (group) {
120   - group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
121   - }
122   - }
123   -};
124   -
125   -InternalLpObj.prototype.getLpNo = function() {
126   - return this._$$_orign_lp_obj.lpNo;
127   -};
128   -InternalLpObj.prototype.getLpName = function() {
129   - return this._$$_orign_lp_obj.lpName;
130   -};
131   -InternalLpObj.prototype.setBxFb5_2 = function(fb) {
132   - this._$_bx_isfb_5_2 = fb;
133   -};
134   -InternalLpObj.prototype.isBxFb5_2 = function() {
135   - return this._$_bx_isfb_5_2;
136   -};
137   -InternalLpObj.prototype.setBxLb = function(lb) {
138   - this._$_bx_isLb = lb;
139   -};
140   -InternalLpObj.prototype.isBxLb = function() {
141   - return this._$_bx_isLb;
142   -};
143   -
144   -InternalLpObj.prototype.setBxFb = function(fb) {
145   - this._$_bx_isfb = fb;
146   -};
147   -InternalLpObj.prototype.isBxFb = function() {
148   - return this._$_bx_isfb;
149   -};
150   -
151   -/**
152   - * 设置路牌的班型描述(最终是设置班次的路牌名字)。
153   - * @param desc 描述
154   - */
155   -InternalLpObj.prototype.setBxDesc = function(desc) {
156   - // 最终原始路牌的名字
157   - this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
158   - // 内部对象的班型描述
159   - this._$_bx_desc = desc;
160   -};
161   -/**
162   - * 获取版型描述
163   - * @returns string
164   - */
165   -InternalLpObj.prototype.getBxDesc = function() {
166   - return this._$_bx_desc;
167   -};
168   -
169   -/**
170   - * 设置纵向最小发车间隔时间。
171   - * @param v
172   - */
173   -InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
174   - // 第一个路牌,都为0
175   - this._$_minVerticalIntervalTime = v;
176   -};
177   -/**
178   - * 获取纵向最小发车间隔时间。
179   - * @returns {number|*}
180   - */
181   -InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
182   - return this._$_minVerticalIntervalTime;
183   -};
184   -
185   -/**
186   - * 设置纵向发车间隔。
187   - * @param iQindex 圈index
188   - * @param iBindex 班次index
189   - * @param iTime 间隔时间
190   - */
191   -InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
192   - this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
193   -};
194   -
195   -/**
196   - * 返回纵向发车间隔。
197   - * @param iQindex 圈index
198   - * @param iBindex 班次index
199   - */
200   -InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
201   - return this._$_aVerticalIntervalTime[iQindex][iBindex];
202   -};
203   -
204   -//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
205   -
206   -/**
207   - * 返回总共班次数。
208   - */
209   -InternalLpObj.prototype.getBcCount = function() {
210   - var i;
211   - var group;
212   - var bccount = 0;
213   - for (i = 0; i < this._$_groupBcArray.length; i++) {
214   - group = this._$_groupBcArray[i];
215   - if (group) {
216   - if (group.getBc1()) {
217   - bccount += 1;
218   - }
219   - if (group.getBc2()) {
220   - bccount += 1;
221   - }
222   - }
223   - }
224   -
225   - return bccount;
226   -};
227   -
228   -/**
229   - * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
230   - * @returns arrays (InternalBcObj)
231   - */
232   -InternalLpObj.prototype.getBcArray = function() {
233   - var bcArray = [];
234   - var i;
235   - var group;
236   - for (i = 0; i < this._$_groupBcArray.length; i++) {
237   - group = this._$_groupBcArray[i];
238   - if (group) {
239   - group.getBc1() ? bcArray.push(group.getBc1()) : "";
240   - group.getBc2() ? bcArray.push(group.getBc2()) : "";
241   - }
242   - }
243   -
244   - return bcArray;
245   -};
246   -
247   -/**
248   - * 获取最小(最早)班次对象。
249   - * @returns [{圈index},{班次index}]
250   - */
251   -InternalLpObj.prototype.getMinBcObjPosition = function() {
252   - var i;
253   - var bIndex = [];
254   - for (i = 0; i < this._$_groupBcArray.length; i++) {
255   - if (this._$_groupBcArray[i].getBc1()) {
256   - bIndex.push(i);
257   - bIndex.push(0);
258   - break;
259   - }
260   - if (this._$_groupBcArray[i].getBc2()) {
261   - bIndex.push(i);
262   - bIndex.push(1);
263   - break;
264   - }
265   - }
266   - return bIndex;
267   -};
268   -
269   -/**
270   - * 获取最大(最晚)班次对象。
271   - * @returns [{圈index},{班次index}]
272   - */
273   -InternalLpObj.prototype.getMaxBcObjPosition = function() {
274   - var i;
275   - var bIndex = [];
276   - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
277   - if (this._$_groupBcArray[i].getBc2()) {
278   - bIndex.push(i);
279   - bIndex.push(1);
280   - break;
281   - }
282   - if (this._$_groupBcArray[i].getBc1()) {
283   - bIndex.push(i);
284   - bIndex.push(0);
285   - break;
286   - }
287   - }
288   - return bIndex;
289   -};
290   -
291   -InternalLpObj.prototype.getMinBcObj = function() {
292   - var i;
293   - var bcObj;
294   - for (i = 0; i < this._$_groupBcArray.length; i++) {
295   - bcObj = this._$_groupBcArray[i].getBc1();
296   - if (bcObj) {
297   - break;
298   - }
299   - bcObj = this._$_groupBcArray[i].getBc2();
300   - if (bcObj) {
301   - break;
302   - }
303   - }
304   - return bcObj;
305   -};
306   -InternalLpObj.prototype.getMaxBcObj = function() {
307   - var i;
308   - var bcObj;
309   - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
310   - bcObj = this._$_groupBcArray[i].getBc2();
311   - if (bcObj) {
312   - break;
313   - }
314   - bcObj = this._$_groupBcArray[i].getBc1();
315   - if (bcObj) {
316   - break;
317   - }
318   - }
319   - return bcObj;
320   -};
321   -
322   -/**
323   - * 获取车次链信息。
324   - * @param num 第几个车次链
325   - * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
326   - */
327   -InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
328   - // 计算总的车次链信息
329   - var aChainInfo = [];
330   - var oChainInfo;
331   - var aBcIndex = this.getMinBcObjPosition();
332   - var oBc;
333   - var iQIndex;
334   - var iBcIndex;
335   - var i;
336   - var bFlag;
337   -
338   - var iBcount = 0;
339   -
340   - if (aBcIndex.length == 2) {
341   - iBcount = 1;
342   - oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
343   - aChainInfo.push(oChainInfo);
344   - bFlag = true;
345   -
346   - // 下一个班次的索引
347   - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
348   - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
349   -
350   - for (i = iQIndex; i < this._$_qCount; i++) {
351   - while (iBcIndex <= 1) {
352   - oBc = this.getBc(i, iBcIndex);
353   - if (!oBc) {
354   - if (bFlag) {
355   - // 车次链结尾是这个班次的前一个班次
356   - oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
357   - oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
358   - oChainInfo.bcount = iBcount;
359   - }
360   -
361   - bFlag = false;
362   - } else {
363   - if (bFlag) {
364   - iBcount ++;
365   - oChainInfo.bcount = iBcount;
366   - } else {
367   - // 下一个车次链开始
368   - iBcount = 1;
369   - oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
370   - aChainInfo.push(oChainInfo);
371   - bFlag = true;
372   - }
373   - }
374   -
375   -
376   - iBcIndex ++;
377   - }
378   - iBcIndex = 0;
379   - }
380   -
381   - }
382   -
383   - return aChainInfo[num];
384   -};
385   -
386   -/**
387   - * 获取车次链的个数。
388   - * @returns int
389   - */
390   -InternalLpObj.prototype.fnGetBcChainCount = function() {
391   - var iChainCount = 0;
392   - var aBcIndex = this.getMinBcObjPosition();
393   -
394   - var oBc;
395   - var iQIndex;
396   - var iBcIndex;
397   - var i;
398   - var bFlag;
399   -
400   - if (aBcIndex.length == 2) {
401   - iChainCount = 1;
402   - bFlag = true;
403   -
404   - // 下一个班次的索引
405   - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
406   - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
407   -
408   - for (i = iQIndex; i < this._$_qCount; i++) {
409   - while (iBcIndex <= 1) {
410   - oBc = this.getBc(i, iBcIndex);
411   - if (!oBc) {
412   - bFlag = false;
413   - } else {
414   - if (bFlag) {
415   -
416   - } else {
417   - iChainCount ++;
418   - bFlag = true;
419   - }
420   - }
421   -
422   -
423   - iBcIndex ++;
424   - }
425   - iBcIndex = 0;
426   - }
427   -
428   - }
429   -
430   -
431   - return iChainCount;
432   -};
433   -
434   -/**
435   - * 在具体位置移除班次。
436   - * @param qIndex 第几圈
437   - * @param bcIndex 第几个班次
438   - */
439   -InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
440   - var group = this._$_groupBcArray[qIndex];
441   - if (bcIndex == 0) {
442   - group.removeBc1();
443   - } else if (bcIndex == 1) {
444   - group.removeBc2();
445   - }
446   -};
447   -
448   -/**
449   - * 使用指定时间匹配返回离之最近的第几圈第几个班次,
450   - * 使用时间差的绝度值,比较,取最小的
451   - * 如果有两个一样的时间差,取比fctime大的时间
452   - * @param fctime moment 比较用时间
453   - * @param groupArray 圈数组
454   - * @param hasUp boolean 计算上行班次
455   - * @param hasDown boolean 计算下行班次
456   - * @returns [{第几圈},{第几个班次}]
457   - */
458   -InternalLpObj.prototype.getgetQBcIndexWithFcTimeFromGroupArray = function(
459   - fctime, groupArray, hasUp, hasDown
460   -) {
461   - var i;
462   - var timediff; // 时间差取绝对值
463   - var qIndex;
464   - var bcIndex;
465   -
466   - var group;
467   - var bc1time;
468   - var bc2time;
469   -
470   - var tempdiff;
471   - for (i = 0; i < this._$_qCount; i++) {
472   - group = groupArray[i];
473   - if (group) {
474   - if (group.getBc1() && hasUp) {
475   - bc1time = group.getBc1().getFcTimeObj();
476   - tempdiff = Math.abs(bc1time.diff(fctime));
477   -
478   - if (!timediff) {
479   - timediff = Math.abs(tempdiff);
480   - qIndex = i;
481   - bcIndex = 0;
482   - } else {
483   - if (tempdiff < timediff) {
484   - timediff = tempdiff;
485   - qIndex = i;
486   - bcIndex = 0;
487   - } if (Math.abs(tempdiff) == timediff) {
488   - if (bc1time.isBefore(fctime)) {
489   - timediff = tempdiff;
490   - qIndex = i;
491   - bcIndex = 0;
492   - }
493   -
494   - }
495   - }
496   - }
497   -
498   - if (group.getBc2() && hasDown) {
499   - bc2time = group.getBc2().getFcTimeObj();
500   - tempdiff = Math.abs(bc2time.diff(fctime));
501   -
502   - if (!timediff) {
503   - timediff = Math.abs(tempdiff);
504   - qIndex = i;
505   - bcIndex = 1;
506   - } else {
507   - if (tempdiff < timediff) {
508   - timediff = tempdiff;
509   - qIndex = i;
510   - bcIndex = 1;
511   - } if (Math.abs(tempdiff) == timediff) {
512   - if (bc2time.isBefore(fctime)) {
513   - timediff = tempdiff;
514   - qIndex = i;
515   - bcIndex = 1;
516   - }
517   -
518   - }
519   - }
520   - }
521   - }
522   - }
523   -
524   - var rst = [];
525   - rst.push(qIndex);
526   - rst.push(bcIndex);
527   -
528   - return rst;
529   -};
530   -
531   -/**
532   - * 使用指定时间匹配返回离之最近的第几圈第几个班次,
533   - * 使用时间差的绝度值,比较,取最小的
534   - * 如果有两个一样的时间差,取比fctime大的时间
535   - * @param fctime moment 比较用时间
536   - * @param hasUp boolean 计算上行班次
537   - * @param hasDown boolean 计算下行班次
538   - * @returns [{第几圈},{第几个班次}]
539   - */
540   -InternalLpObj.prototype.getQBcIndexWithFcTime = function(
541   - fctime, hasUp, hasDown
542   -) {
543   - return this.getgetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
544   -};
545   -
546   -//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
547   -
548   -/**
549   - * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
550   - * 注意,之前有班次会删除后再创建。
551   - * @param startTime 开始时间
552   - * @param endTime 结束时间
553   - * @param isUp 第一个班次是上行还是下行
554   - * @param fromQ 从第几圈开始加入
555   - * @param paramObj 参数对象
556   - * @param factory 工厂对象
557   - */
558   -InternalLpObj.prototype.initDataFromTimeToTime = function(
559   - startTime,
560   - endTime,
561   - isUp,
562   - fromQ,
563   - paramObj,
564   - factory) {
565   -
566   - var bcData = []; // 班次数组
567   - var bcObj;
568   - var kssj = startTime;
569   - var fcno = 1; // 发车顺序号
570   - var bcCount = 1; // 班次数
571   - do {
572   - bcObj = factory.createBcObj(
573   - this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
574   - bcData.push(bcObj);
575   -
576   - kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
577   - fcno ++;
578   - bcCount ++;
579   - isUp = !isUp;
580   - } while(kssj.isBefore(endTime));
581   - bcCount--;
582   -
583   - //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
584   - //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
585   - //console.log("endtime: " + endTime.format("HH:mm"));
586   -
587   - if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
588   - // 如果最后一个班次的到达时间超过结束时间,也要去除
589   - bcData.splice(bcCount - 1, 1);
590   - }
591   -
592   - this._initDataFromLbBcArray(bcData, fromQ);
593   -
594   -};
595   -
596   -/**
597   - * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
598   - * @param bcArray 连班班次数组
599   - * @param fromQ 从第几圈开始加入
600   - */
601   -InternalLpObj.prototype._initDataFromLbBcArray = function(
602   - bcArray,
603   - fromQ
604   -) {
605   - var _bc1Obj;
606   - var _bc2Obj;
607   - var _qObj;
608   -
609   - // 第一班次是上行还是下行
610   - var isUp = bcArray[0].isUp();
611   -
612   - if (bcArray.length > 0 && fromQ < this._$_qCount) {
613   - // 构造圈数
614   - if (isUp != this._$_isUp) {
615   - // 如果方向不一致,意味着第一个班次是半圈
616   - // 加半圈,并加在bc2上
617   - _bc2Obj = bcArray.slice(0, 1)[0];
618   - _qObj = new InternalGroupObj(
619   - this,
620   - this._$_isUp,
621   - undefined,
622   - _bc2Obj
623   - );
624   - _bc2Obj.setGroup(_qObj);
625   - this._$_groupBcArray[fromQ] = _qObj;
626   -
627   - bcArray.splice(0, 1);
628   - fromQ ++;
629   - }
630   -
631   - var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
632   - var qCount2 = bcArray.length % 2; // 最后是否有半圈
633   -
634   - while (fromQ < this._$_qCount) {
635   - if (qCount1 > 0) {
636   - _bc1Obj = bcArray.slice(0, 1)[0];
637   - _bc2Obj = bcArray.slice(1, 2)[0];
638   - _qObj = new InternalGroupObj(
639   - this,
640   - this._$_isUp,
641   - _bc1Obj,
642   - _bc2Obj
643   - );
644   - _bc1Obj.setGroup(_qObj);
645   - _bc2Obj.setGroup(_qObj);
646   - this._$_groupBcArray[fromQ] = _qObj;
647   -
648   - bcArray.splice(0, 2);
649   - qCount1 --;
650   - } else if (qCount2 > 0) {
651   - // 加半圈,并加在bc1上
652   - _bc1Obj = bcArray.slice(0, 1)[0];
653   - _qObj = new InternalGroupObj(
654   - this,
655   - this._$_isUp,
656   - _bc1Obj,
657   - undefined
658   - );
659   - _bc1Obj.setGroup(_qObj);
660   - this._$_groupBcArray[fromQ] = _qObj;
661   -
662   - bcArray.splice(0, 1);
663   - qCount2 --;
664   - } else {
665   - break;
666   - }
667   -
668   - fromQ ++;
669   - }
670   - }
671   -};
672   -
673   -//-------------------------- 其他方法 ----------------------------//
674   -
675   -/**
676   - * 从指定位置的班次开始,往后所有的班次修正发车时间
677   - * @param groupIndex
678   - * @param bcIndex
679   - * @param time
680   - */
681   -InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
682   - var i;
683   - var oCurBc;
684   -
685   - // 修正之前班次的停站时间
686   - //oCurBc = this.getBc(
687   - // bcIndex == 0 ? groupIndex - 1 : groupIndex,
688   - // bcIndex == 1 ? 0 : 1
689   - //);
690   - //if (oCurBc) {
691   - // oCurBc.setStopTime(oCurBc.getStopTime() + time);
692   - //}
693   -
694   -
695   - for (i = groupIndex; i < this._$_qCount; i++) {
696   - if (bcIndex == 0) {
697   - oCurBc = this.getBc(i, 0);
698   - if (oCurBc) {
699   - oCurBc.addMinuteToFcsj(time);
700   - }
701   - oCurBc = this.getBc(i, 1);
702   - if (oCurBc) {
703   - oCurBc.addMinuteToFcsj(time);
704   - }
705   -
706   - } else {
707   - oCurBc = this.getBc(i, 1);
708   - if (oCurBc) {
709   - oCurBc.addMinuteToFcsj(time);
710   - }
711   -
712   - }
713   -
714   - bcIndex = 0;
715   - }
716   -};
717   -
718   -/**
719   - * 在指定位置添加一个吃饭班次。
720   - * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
721   - * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
722   - * @param groupIndex
723   - * @param bcIndex
724   - * @param factory
725   - * @param paramObj
726   - * @returns int 相差时间(吃饭时间距离和停站时间相差值)
727   - */
728   -InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
729   - var oPreBc;
730   - var oEatBc;
731   - var iBcModifyTime;
732   - oPreBc = this.getBc( // 前一个邻接班次
733   - bcIndex == 0 ? groupIndex - 1 : groupIndex,
734   - bcIndex == 1 ? 0 : 1);
735   - if (oPreBc) { // 存在前一个班次
736   - oEatBc = factory.createBcObj(
737   - this,
738   - "cf",
739   - !oPreBc.isUp(), // 和上一个班次方向相反
740   - 1,
741   - oPreBc.getArrTimeObj(), // 使用上一个班次的到达时间作为开始时间
742   - paramObj
743   - );
744   -
745   - //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间
746   -
747   - // 修正之后的班次发车时间
748   - // 注意:之后那个班次发车时间就是吃饭班次的到达时间
749   - iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");
750   - this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);
751   -
752   - oPreBc.setStopTime(0);
753   - this._$_other_bc_array.push(oEatBc);
754   -
755   - return iBcModifyTime;
756   - } else {
757   - return false;
758   - }
759   -
760   -};
761   -
762   -
763   -// TODO
764   -
765   -/**
766   - *
767   - *
768   - */
769   -InternalLpObj.prototype.calcuLpBx = function() {
770   -
771   -};
772   -
773   -
  1 +/**
  2 + * 内部路牌对象。
  3 + * @constructor
  4 + */
  5 +var InternalLpObj = function(
  6 + orilpObj, // 原始路牌对象
  7 + qCount, // 总共多少圈
  8 + isUp // 圈是以上行开始还是下行开始
  9 +) {
  10 + // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
  11 + this._$$_orign_lp_obj = orilpObj;
  12 +
  13 + this._$_isUp = isUp;
  14 +
  15 + // 路牌的圈数,注意每个路牌的圈数都是一致的,
  16 + // 但并不是每一圈都有值
  17 + // 第1圈从上标线开始
  18 + // 第0圈表示中标线的第一个班次组成的半圈
  19 + // 有多少圈根据最终迭代的结果来看
  20 + this._$_qCount = qCount;
  21 + // 保存的是 InternalGroupBcObj 对象
  22 + this._$_groupBcArray = new Array(qCount);
  23 +
  24 + var i;
  25 + for (i = 0; i < this._$_qCount; i++) {
  26 + this._$_groupBcArray[i] = new InternalGroupObj(
  27 + this, this._$_isUp, undefined, undefined);
  28 + }
  29 +
  30 + // 距离上一个路牌的最小发车间隔时间
  31 + // 用于纵向添加班次的时候使用
  32 + // 默认第一个路牌为0
  33 + this._$_minVerticalIntervalTime = 0;
  34 +
  35 + // 详细记录每圈每个方向上的发车间隔时间
  36 + // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
  37 + // 第一个方向是否上行由 _$_isUp 决定
  38 + // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
  39 + // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
  40 + this._$_aVerticalIntervalTime = new Array(this._$_qCount);
  41 + var i;
  42 + for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
  43 + this._$_aVerticalIntervalTime[i] = new Array(2);
  44 + }
  45 +
  46 + // 班型的相关变量
  47 + this._$_bx_isLb = false; // 是否连班
  48 + this._$_bx_isfb = false; // 是否分班
  49 + this._$_bx_isfb_5_2 = false; // 是否5休2分班
  50 + this._$_bx_desc; // 班型描述(默认为路牌编号)
  51 +
  52 + // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
  53 + this._$_other_bc_array = [];
  54 +
  55 + // TODO:
  56 +
  57 +};
  58 +
  59 +//------------------- get/set 方法 -------------------//
  60 +
  61 +InternalLpObj.prototype.getOtherBcArray = function() {
  62 + return this._$_other_bc_array;
  63 +};
  64 +InternalLpObj.prototype.addOtherBcArray = function(ba) {
  65 + this._$_other_bc_array = this._$_other_bc_array.concat(ba);
  66 +};
  67 +
  68 +/**
  69 + * 获取圈
  70 + * @param qIndex 圈index
  71 + */
  72 +InternalLpObj.prototype.getGroup = function(qIndex) {
  73 + return this._$_groupBcArray[qIndex];
  74 +};
  75 +
  76 +/**
  77 + * 获取班次。
  78 + * @param qIndex 第几圈
  79 + * @param bcIndex 第几个班次
  80 + */
  81 +InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
  82 + var group = this._$_groupBcArray[qIndex];
  83 + var bc;
  84 + if (bcIndex == 0) {
  85 + bc = group.getBc1();
  86 + } else if (bcIndex == 1) {
  87 + bc = group.getBc2();
  88 + }
  89 + return bc;
  90 +};
  91 +
  92 +/**
  93 + * 在具体位置设置班次。
  94 + * @param qIndex 第几圈
  95 + * @param bcIndex 第几个班次
  96 + * @param bc 班次对象
  97 + */
  98 +InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
  99 + var group = this._$_groupBcArray[qIndex];
  100 + if (bcIndex == 0) {
  101 + group.setBc1(bc);
  102 + bc.setGroup(group);
  103 + } else if (bcIndex == 1) {
  104 + group.setBc2(bc);
  105 + bc.setGroup(group);
  106 + }
  107 +};
  108 +
  109 +/**
  110 + * 设置原始路牌对象。
  111 + * @param lpObj 原始路牌对象
  112 + */
  113 +InternalLpObj.prototype.setLp = function(lpObj) {
  114 + this._$$_orign_lp_obj = lpObj;
  115 + var i;
  116 + var group;
  117 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  118 + group = this._$_groupBcArray[i];
  119 + if (group) {
  120 + group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
  121 + }
  122 + }
  123 +};
  124 +
  125 +InternalLpObj.prototype.getLpNo = function() {
  126 + return this._$$_orign_lp_obj.lpNo;
  127 +};
  128 +InternalLpObj.prototype.getLpName = function() {
  129 + return this._$$_orign_lp_obj.lpName;
  130 +};
  131 +InternalLpObj.prototype.setBxFb5_2 = function(fb) {
  132 + this._$_bx_isfb_5_2 = fb;
  133 +};
  134 +InternalLpObj.prototype.isBxFb5_2 = function() {
  135 + return this._$_bx_isfb_5_2;
  136 +};
  137 +InternalLpObj.prototype.setBxLb = function(lb) {
  138 + this._$_bx_isLb = lb;
  139 +};
  140 +InternalLpObj.prototype.isBxLb = function() {
  141 + return this._$_bx_isLb;
  142 +};
  143 +
  144 +InternalLpObj.prototype.setBxFb = function(fb) {
  145 + this._$_bx_isfb = fb;
  146 +};
  147 +InternalLpObj.prototype.isBxFb = function() {
  148 + return this._$_bx_isfb;
  149 +};
  150 +
  151 +/**
  152 + * 设置路牌的班型描述(最终是设置班次的路牌名字)。
  153 + * @param desc 描述
  154 + */
  155 +InternalLpObj.prototype.setBxDesc = function(desc) {
  156 + // 最终原始路牌的名字
  157 + this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
  158 + // 内部对象的班型描述
  159 + this._$_bx_desc = desc;
  160 +};
  161 +/**
  162 + * 获取版型描述
  163 + * @returns string
  164 + */
  165 +InternalLpObj.prototype.getBxDesc = function() {
  166 + return this._$_bx_desc;
  167 +};
  168 +
  169 +/**
  170 + * 设置纵向最小发车间隔时间。
  171 + * @param v
  172 + */
  173 +InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
  174 + // 第一个路牌,都为0
  175 + this._$_minVerticalIntervalTime = v;
  176 +};
  177 +/**
  178 + * 获取纵向最小发车间隔时间。
  179 + * @returns {number|*}
  180 + */
  181 +InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
  182 + return this._$_minVerticalIntervalTime;
  183 +};
  184 +
  185 +/**
  186 + * 设置纵向发车间隔。
  187 + * @param iQindex 圈index
  188 + * @param iBindex 班次index
  189 + * @param iTime 间隔时间
  190 + */
  191 +InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
  192 + this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
  193 +};
  194 +
  195 +/**
  196 + * 返回纵向发车间隔。
  197 + * @param iQindex 圈index
  198 + * @param iBindex 班次index
  199 + */
  200 +InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
  201 + return this._$_aVerticalIntervalTime[iQindex][iBindex];
  202 +};
  203 +
  204 +//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
  205 +
  206 +/**
  207 + * 返回总共班次数。
  208 + */
  209 +InternalLpObj.prototype.getBcCount = function() {
  210 + var i;
  211 + var group;
  212 + var bccount = 0;
  213 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  214 + group = this._$_groupBcArray[i];
  215 + if (group) {
  216 + if (group.getBc1()) {
  217 + bccount += 1;
  218 + }
  219 + if (group.getBc2()) {
  220 + bccount += 1;
  221 + }
  222 + }
  223 + }
  224 +
  225 + return bccount;
  226 +};
  227 +
  228 +/**
  229 + * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
  230 + * @returns arrays (InternalBcObj)
  231 + */
  232 +InternalLpObj.prototype.getBcArray = function() {
  233 + var bcArray = [];
  234 + var i;
  235 + var group;
  236 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  237 + group = this._$_groupBcArray[i];
  238 + if (group) {
  239 + group.getBc1() ? bcArray.push(group.getBc1()) : "";
  240 + group.getBc2() ? bcArray.push(group.getBc2()) : "";
  241 + }
  242 + }
  243 +
  244 + return bcArray;
  245 +};
  246 +
  247 +/**
  248 + * 获取最小(最早)班次对象。
  249 + * @returns [{圈index},{班次index}]
  250 + */
  251 +InternalLpObj.prototype.getMinBcObjPosition = function() {
  252 + var i;
  253 + var bIndex = [];
  254 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  255 + if (this._$_groupBcArray[i].getBc1()) {
  256 + bIndex.push(i);
  257 + bIndex.push(0);
  258 + break;
  259 + }
  260 + if (this._$_groupBcArray[i].getBc2()) {
  261 + bIndex.push(i);
  262 + bIndex.push(1);
  263 + break;
  264 + }
  265 + }
  266 + return bIndex;
  267 +};
  268 +
  269 +/**
  270 + * 获取最大(最晚)班次对象。
  271 + * @returns [{圈index},{班次index}]
  272 + */
  273 +InternalLpObj.prototype.getMaxBcObjPosition = function() {
  274 + var i;
  275 + var bIndex = [];
  276 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  277 + if (this._$_groupBcArray[i].getBc2()) {
  278 + bIndex.push(i);
  279 + bIndex.push(1);
  280 + break;
  281 + }
  282 + if (this._$_groupBcArray[i].getBc1()) {
  283 + bIndex.push(i);
  284 + bIndex.push(0);
  285 + break;
  286 + }
  287 + }
  288 + return bIndex;
  289 +};
  290 +
  291 +InternalLpObj.prototype.getMinBcObj = function() {
  292 + var i;
  293 + var bcObj;
  294 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  295 + bcObj = this._$_groupBcArray[i].getBc1();
  296 + if (bcObj) {
  297 + break;
  298 + }
  299 + bcObj = this._$_groupBcArray[i].getBc2();
  300 + if (bcObj) {
  301 + break;
  302 + }
  303 + }
  304 + return bcObj;
  305 +};
  306 +InternalLpObj.prototype.getMaxBcObj = function() {
  307 + var i;
  308 + var bcObj;
  309 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  310 + bcObj = this._$_groupBcArray[i].getBc2();
  311 + if (bcObj) {
  312 + break;
  313 + }
  314 + bcObj = this._$_groupBcArray[i].getBc1();
  315 + if (bcObj) {
  316 + break;
  317 + }
  318 + }
  319 + return bcObj;
  320 +};
  321 +
  322 +/**
  323 + * 获取车次链信息。
  324 + * @param num 第几个车次链
  325 + * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
  326 + */
  327 +InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
  328 + // 计算总的车次链信息
  329 + var aChainInfo = [];
  330 + var oChainInfo;
  331 + var aBcIndex = this.getMinBcObjPosition();
  332 + var oBc;
  333 + var iQIndex;
  334 + var iBcIndex;
  335 + var i;
  336 + var bFlag;
  337 +
  338 + var iBcount = 0;
  339 +
  340 + if (aBcIndex.length == 2) {
  341 + iBcount = 1;
  342 + oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
  343 + aChainInfo.push(oChainInfo);
  344 + bFlag = true;
  345 +
  346 + // 下一个班次的索引
  347 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  348 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  349 +
  350 + for (i = iQIndex; i < this._$_qCount; i++) {
  351 + while (iBcIndex <= 1) {
  352 + oBc = this.getBc(i, iBcIndex);
  353 + if (!oBc) {
  354 + if (bFlag) {
  355 + // 车次链结尾是这个班次的前一个班次
  356 + oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
  357 + oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
  358 + oChainInfo.bcount = iBcount;
  359 + }
  360 +
  361 + bFlag = false;
  362 + } else {
  363 + if (bFlag) {
  364 + iBcount ++;
  365 + oChainInfo.bcount = iBcount;
  366 + } else {
  367 + // 下一个车次链开始
  368 + iBcount = 1;
  369 + oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
  370 + aChainInfo.push(oChainInfo);
  371 + bFlag = true;
  372 + }
  373 + }
  374 +
  375 +
  376 + iBcIndex ++;
  377 + }
  378 + iBcIndex = 0;
  379 + }
  380 +
  381 + }
  382 +
  383 + return aChainInfo[num];
  384 +};
  385 +
  386 +/**
  387 + * 获取车次链的个数。
  388 + * @returns int
  389 + */
  390 +InternalLpObj.prototype.fnGetBcChainCount = function() {
  391 + var iChainCount = 0;
  392 + var aBcIndex = this.getMinBcObjPosition();
  393 +
  394 + var oBc;
  395 + var iQIndex;
  396 + var iBcIndex;
  397 + var i;
  398 + var bFlag;
  399 +
  400 + if (aBcIndex.length == 2) {
  401 + iChainCount = 1;
  402 + bFlag = true;
  403 +
  404 + // 下一个班次的索引
  405 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  406 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  407 +
  408 + for (i = iQIndex; i < this._$_qCount; i++) {
  409 + while (iBcIndex <= 1) {
  410 + oBc = this.getBc(i, iBcIndex);
  411 + if (!oBc) {
  412 + bFlag = false;
  413 + } else {
  414 + if (bFlag) {
  415 +
  416 + } else {
  417 + iChainCount ++;
  418 + bFlag = true;
  419 + }
  420 + }
  421 +
  422 +
  423 + iBcIndex ++;
  424 + }
  425 + iBcIndex = 0;
  426 + }
  427 +
  428 + }
  429 +
  430 +
  431 + return iChainCount;
  432 +};
  433 +
  434 +/**
  435 + * 在具体位置移除班次。
  436 + * @param qIndex 第几圈
  437 + * @param bcIndex 第几个班次
  438 + */
  439 +InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
  440 + var group = this._$_groupBcArray[qIndex];
  441 + if (bcIndex == 0) {
  442 + group.removeBc1();
  443 + } else if (bcIndex == 1) {
  444 + group.removeBc2();
  445 + }
  446 +};
  447 +
  448 +/**
  449 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  450 + * 使用时间差的绝度值,比较,取最小的
  451 + * 如果有两个一样的时间差,取比fctime大的时间
  452 + * @param fctime moment 比较用时间
  453 + * @param groupArray 圈数组
  454 + * @param hasUp boolean 计算上行班次
  455 + * @param hasDown boolean 计算下行班次
  456 + * @returns [{第几圈},{第几个班次}]
  457 + */
  458 +InternalLpObj.prototype.getgetQBcIndexWithFcTimeFromGroupArray = function(
  459 + fctime, groupArray, hasUp, hasDown
  460 +) {
  461 + var i;
  462 + var timediff; // 时间差取绝对值
  463 + var qIndex;
  464 + var bcIndex;
  465 +
  466 + var group;
  467 + var bc1time;
  468 + var bc2time;
  469 +
  470 + var tempdiff;
  471 + for (i = 0; i < this._$_qCount; i++) {
  472 + group = groupArray[i];
  473 + if (group) {
  474 + if (group.getBc1() && hasUp) {
  475 + bc1time = group.getBc1().getFcTimeObj();
  476 + tempdiff = Math.abs(bc1time.diff(fctime));
  477 +
  478 + if (!timediff) {
  479 + timediff = Math.abs(tempdiff);
  480 + qIndex = i;
  481 + bcIndex = 0;
  482 + } else {
  483 + if (tempdiff < timediff) {
  484 + timediff = tempdiff;
  485 + qIndex = i;
  486 + bcIndex = 0;
  487 + } if (Math.abs(tempdiff) == timediff) {
  488 + if (bc1time.isBefore(fctime)) {
  489 + timediff = tempdiff;
  490 + qIndex = i;
  491 + bcIndex = 0;
  492 + }
  493 +
  494 + }
  495 + }
  496 + }
  497 +
  498 + if (group.getBc2() && hasDown) {
  499 + bc2time = group.getBc2().getFcTimeObj();
  500 + tempdiff = Math.abs(bc2time.diff(fctime));
  501 +
  502 + if (!timediff) {
  503 + timediff = Math.abs(tempdiff);
  504 + qIndex = i;
  505 + bcIndex = 1;
  506 + } else {
  507 + if (tempdiff < timediff) {
  508 + timediff = tempdiff;
  509 + qIndex = i;
  510 + bcIndex = 1;
  511 + } if (Math.abs(tempdiff) == timediff) {
  512 + if (bc2time.isBefore(fctime)) {
  513 + timediff = tempdiff;
  514 + qIndex = i;
  515 + bcIndex = 1;
  516 + }
  517 +
  518 + }
  519 + }
  520 + }
  521 + }
  522 + }
  523 +
  524 + var rst = [];
  525 + rst.push(qIndex);
  526 + rst.push(bcIndex);
  527 +
  528 + return rst;
  529 +};
  530 +
  531 +/**
  532 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  533 + * 使用时间差的绝度值,比较,取最小的
  534 + * 如果有两个一样的时间差,取比fctime大的时间
  535 + * @param fctime moment 比较用时间
  536 + * @param hasUp boolean 计算上行班次
  537 + * @param hasDown boolean 计算下行班次
  538 + * @returns [{第几圈},{第几个班次}]
  539 + */
  540 +InternalLpObj.prototype.getQBcIndexWithFcTime = function(
  541 + fctime, hasUp, hasDown
  542 +) {
  543 + return this.getgetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
  544 +};
  545 +
  546 +//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
  547 +
  548 +/**
  549 + * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
  550 + * 注意,之前有班次会删除后再创建。
  551 + * @param startTime 开始时间
  552 + * @param endTime 结束时间
  553 + * @param isUp 第一个班次是上行还是下行
  554 + * @param fromQ 从第几圈开始加入
  555 + * @param paramObj 参数对象
  556 + * @param factory 工厂对象
  557 + */
  558 +InternalLpObj.prototype.initDataFromTimeToTime = function(
  559 + startTime,
  560 + endTime,
  561 + isUp,
  562 + fromQ,
  563 + paramObj,
  564 + factory) {
  565 +
  566 + var bcData = []; // 班次数组
  567 + var bcObj;
  568 + var kssj = startTime;
  569 + var fcno = 1; // 发车顺序号
  570 + var bcCount = 1; // 班次数
  571 + do {
  572 + bcObj = factory.createBcObj(
  573 + this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
  574 + bcData.push(bcObj);
  575 +
  576 + kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
  577 + fcno ++;
  578 + bcCount ++;
  579 + isUp = !isUp;
  580 + } while(kssj.isBefore(endTime));
  581 + bcCount--;
  582 +
  583 + //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
  584 + //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
  585 + //console.log("endtime: " + endTime.format("HH:mm"));
  586 +
  587 + if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
  588 + // 如果最后一个班次的到达时间超过结束时间,也要去除
  589 + bcData.splice(bcCount - 1, 1);
  590 + }
  591 +
  592 + this._initDataFromLbBcArray(bcData, fromQ);
  593 +
  594 +};
  595 +
  596 +/**
  597 + * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
  598 + * @param bcArray 连班班次数组
  599 + * @param fromQ 从第几圈开始加入
  600 + */
  601 +InternalLpObj.prototype._initDataFromLbBcArray = function(
  602 + bcArray,
  603 + fromQ
  604 +) {
  605 + var _bc1Obj;
  606 + var _bc2Obj;
  607 + var _qObj;
  608 +
  609 + // 第一班次是上行还是下行
  610 + var isUp = bcArray[0].isUp();
  611 +
  612 + if (bcArray.length > 0 && fromQ < this._$_qCount) {
  613 + // 构造圈数
  614 + if (isUp != this._$_isUp) {
  615 + // 如果方向不一致,意味着第一个班次是半圈
  616 + // 加半圈,并加在bc2上
  617 + _bc2Obj = bcArray.slice(0, 1)[0];
  618 + _qObj = new InternalGroupObj(
  619 + this,
  620 + this._$_isUp,
  621 + undefined,
  622 + _bc2Obj
  623 + );
  624 + _bc2Obj.setGroup(_qObj);
  625 + this._$_groupBcArray[fromQ] = _qObj;
  626 +
  627 + bcArray.splice(0, 1);
  628 + fromQ ++;
  629 + }
  630 +
  631 + var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
  632 + var qCount2 = bcArray.length % 2; // 最后是否有半圈
  633 +
  634 + while (fromQ < this._$_qCount) {
  635 + if (qCount1 > 0) {
  636 + _bc1Obj = bcArray.slice(0, 1)[0];
  637 + _bc2Obj = bcArray.slice(1, 2)[0];
  638 + _qObj = new InternalGroupObj(
  639 + this,
  640 + this._$_isUp,
  641 + _bc1Obj,
  642 + _bc2Obj
  643 + );
  644 + _bc1Obj.setGroup(_qObj);
  645 + _bc2Obj.setGroup(_qObj);
  646 + this._$_groupBcArray[fromQ] = _qObj;
  647 +
  648 + bcArray.splice(0, 2);
  649 + qCount1 --;
  650 + } else if (qCount2 > 0) {
  651 + // 加半圈,并加在bc1上
  652 + _bc1Obj = bcArray.slice(0, 1)[0];
  653 + _qObj = new InternalGroupObj(
  654 + this,
  655 + this._$_isUp,
  656 + _bc1Obj,
  657 + undefined
  658 + );
  659 + _bc1Obj.setGroup(_qObj);
  660 + this._$_groupBcArray[fromQ] = _qObj;
  661 +
  662 + bcArray.splice(0, 1);
  663 + qCount2 --;
  664 + } else {
  665 + break;
  666 + }
  667 +
  668 + fromQ ++;
  669 + }
  670 + }
  671 +};
  672 +
  673 +//-------------------------- 其他方法 ----------------------------//
  674 +
  675 +/**
  676 + * 从指定位置的班次开始,往后所有的班次修正发车时间
  677 + * @param groupIndex
  678 + * @param bcIndex
  679 + * @param time
  680 + */
  681 +InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
  682 + var i;
  683 + var oCurBc;
  684 +
  685 + // 修正之前班次的停站时间
  686 + //oCurBc = this.getBc(
  687 + // bcIndex == 0 ? groupIndex - 1 : groupIndex,
  688 + // bcIndex == 1 ? 0 : 1
  689 + //);
  690 + //if (oCurBc) {
  691 + // oCurBc.setStopTime(oCurBc.getStopTime() + time);
  692 + //}
  693 +
  694 +
  695 + for (i = groupIndex; i < this._$_qCount; i++) {
  696 + if (bcIndex == 0) {
  697 + oCurBc = this.getBc(i, 0);
  698 + if (oCurBc) {
  699 + oCurBc.addMinuteToFcsj(time);
  700 + }
  701 + oCurBc = this.getBc(i, 1);
  702 + if (oCurBc) {
  703 + oCurBc.addMinuteToFcsj(time);
  704 + }
  705 +
  706 + } else {
  707 + oCurBc = this.getBc(i, 1);
  708 + if (oCurBc) {
  709 + oCurBc.addMinuteToFcsj(time);
  710 + }
  711 +
  712 + }
  713 +
  714 + bcIndex = 0;
  715 + }
  716 +};
  717 +
  718 +/**
  719 + * 在指定位置添加一个吃饭班次。
  720 + * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
  721 + * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
  722 + * @param groupIndex
  723 + * @param bcIndex
  724 + * @param factory
  725 + * @param paramObj
  726 + * @returns int 相差时间(吃饭时间距离和停站时间相差值)
  727 + */
  728 +InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
  729 + var oPreBc;
  730 + var oEatBc;
  731 + var iBcModifyTime;
  732 + oPreBc = this.getBc( // 前一个邻接班次
  733 + bcIndex == 0 ? groupIndex - 1 : groupIndex,
  734 + bcIndex == 1 ? 0 : 1);
  735 + if (oPreBc) { // 存在前一个班次
  736 + oEatBc = factory.createBcObj(
  737 + this,
  738 + "cf",
  739 + !oPreBc.isUp(), // 和上一个班次方向相反
  740 + 1,
  741 + oPreBc.getArrTimeObj(), // 使用上一个班次的到达时间作为开始时间
  742 + paramObj
  743 + );
  744 +
  745 + //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间
  746 +
  747 + // 修正之后的班次发车时间
  748 + // 注意:之后那个班次发车时间就是吃饭班次的到达时间
  749 + iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");
  750 + this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);
  751 +
  752 + oPreBc.setStopTime(0);
  753 + this._$_other_bc_array.push(oEatBc);
  754 +
  755 + return iBcModifyTime;
  756 + } else {
  757 + return false;
  758 + }
  759 +
  760 +};
  761 +
  762 +
  763 +// TODO
  764 +
  765 +/**
  766 + *
  767 + *
  768 + */
  769 +InternalLpObj.prototype.calcuLpBx = function() {
  770 +
  771 +};
  772 +
  773 +
... ...
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalScheduleObj.js
1   -/**
2   - * 内部行车计划对象。
3   - * @constructor
4   - */
5   -var InternalScheduleObj = function(paramObj, lpArray, factory) {
6   - // 参数对象
7   - var _paramObj = paramObj;
8   - // 外部的路牌数组
9   - var _lpArray = lpArray;
10   - // 工厂对象
11   - var _factory = factory;
12   -
13   - //------------------ 初始化方法1,以及计算关联的内部变量 -----------------//
14   - var _qIsUp; // 每一圈是上行开始还是下行开始
15   - var _qCount = 0; // 总的圈数
16   - var _internalLpArray = []; // 内部对象数组
17   - var _aBxDesc = [ // 各种班型描述(班型名称,平均工时,平均需要的班次数,平均工时)
18   - {'sType':'六工一休', 'fHoursV':6.66, 'fBcCount': 0, 'fAverTime': 0},
19   - {'sType':'五工一休', 'fHoursV':6.85, 'fBcCount': 0, 'fAverTime': 0},
20   - {'sType':'四工一休', 'fHoursV':7.14, 'fBcCount': 0, 'fAverTime': 0},
21   - {'sType':'三工一休', 'fHoursV':7.61, 'fBcCount': 0, 'fAverTime': 0},
22   - {'sType':'二工一休', 'fHoursV':8.57, 'fBcCount': 0, 'fAverTime': 0},
23   - {'sType':'一工一休', 'fHoursV':11.42, 'fBcCount': 0, 'fAverTime': 0},
24   - {'sType':'五工二休', 'fHoursV':7.99, 'fBcCount': 0, 'fAverTime': 0},
25   - {'sType':'无工休', 'fHoursV':5.43, 'fBcCount': 0, 'fAverTime': 0}
26   - ];
27   -
28   - var _fnInitFun1 = function() { // 初始化方法1
29   - console.log("//---------------- 行车计划,初始化方法1 start ----------------//");
30   -
31   - //----------------------- 1、确定上标线的方向,圈的方向 -------------------//
32   -
33   - // 确定_qIsUp,哪个方向的首班车晚就用哪个
34   - _qIsUp = _paramObj.getUpFirstDTimeObj().isBefore(
35   - _paramObj.getDownFirstDTimeObj()) ? false : true;
36   - // 上标线开始时间,就是方向的首班车时间
37   - var st = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
38   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
39   - var et;
40   - var et_IsUp;
41   - if (_paramObj.getUpLastDtimeObj().isBefore(
42   - _paramObj.getDownLastDTimeObj())) {
43   - et = _paramObj.getDownLastDTimeObj();
44   - et_IsUp = false;
45   - } else {
46   - et = _paramObj.getUpLastDtimeObj();
47   - et_IsUp = true;
48   - }
49   -
50   - //------------------------ 2、计算总共有多少圈 ------------------------//
51   -
52   - // 以开始时间,结束时间,构造上标线用连班班次发车时间
53   - var bcFcsjArrays = []; // 班次发车时间对象数组
54   - var bcArsjArrays = []; // 班次到达时间对象数组
55   - var isUp = _qIsUp; // 方向
56   - var bcCount = 1; // 班次数
57   -
58   - var _kssj = st; // 开始时间
59   - var _bcsj = paramObj.calcuTravelTime(_kssj, isUp); // 班次历时
60   - var _arrsj = paramObj.addMinute(_kssj, _bcsj); // 到达时间
61   - var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj); // 停站时间
62   -
63   - do {
64   - bcFcsjArrays.push(_kssj);
65   - bcArsjArrays.push(_arrsj);
66   -
67   - _kssj = paramObj.addMinute(_kssj, _bcsj + _stoptime);
68   - _bcsj = paramObj.calcuTravelTime(_kssj, isUp);
69   - _arrsj = paramObj.addMinute(_kssj, _bcsj);
70   - _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
71   -
72   - bcCount ++;
73   - isUp = !isUp;
74   - } while(_kssj.isBefore(et));
75   - bcCount--; // 因为先做do,所以总的班次要减1
76   - if (bcCount > 0 && bcArsjArrays[bcCount - 1].isAfter(et)) {
77   - // 如果最后一个班次的到达时间超过结束时间,也要去除
78   - bcFcsjArrays.splice(bcCount - 1, 1);
79   - bcArsjArrays.splice(bcCount - 1, 1);
80   - bcCount--;
81   - }
82   - var _qCount_p1 = Math.floor(bcCount / 2); // 2个班次一圈
83   - var _qCount_p2 = bcCount % 2; // 余下的1个班次也算一圈
84   -
85   - // 利用连班数组计算圈数
86   - _qCount = 1; // 前面加1圈,补中标线的班次
87   - _qCount += _qCount_p1;
88   - _qCount += _qCount_p2;
89   -
90   - // 计算最后是不是还要补一圈
91   - if (_qCount > 1) { // 总的圈数就1圈,没必要加了(其实是不可能的,除非参数里问题)
92   - if (_qCount_p2 == 0) { // 没有余下班次,整数圈数
93   - // 最后一个班次的方向一定和开始的方向相反,如:上-下,上-下,上-下,一共三圈,最后一个班次为下行
94   - // 判定最后一个班次的方向和上标线判定结束时间的班次方向是否一致
95   - if (!_qIsUp == et_IsUp) {
96   - // 一致不用加圈数
97   - } else {
98   - // 不一致需要加圈补最后一个结束时间班次
99   - _qCount ++;
100   - }
101   - } else {
102   - // 有余下的圈数,最后要不补的班次不管上行,下行都在这一圈里
103   - // 不需要在补圈数了
104   - }
105   - }
106   -
107   - //------------------------ 3、根据路牌数,圈数创建路牌对象 ----------------------//
108   -
109   - // 创建内部的路牌数组,并把之前的连班路牌添加进上标线路牌中
110   - var i;
111   - for (i = 0; i < _lpArray.length; i++) {
112   - _internalLpArray.push(new InternalLpObj(_lpArray[i], _qCount, _qIsUp));
113   - }
114   - // 初始化上标线,从第1圈开始
115   - _internalLpArray[0].initDataFromTimeToTime(bcFcsjArrays[0], et, _qIsUp, 1, _paramObj, _factory);
116   -
117   - // 以上标线为基础,计算各种班型工时对应的圈数、班次数
118   - var aBcArray = _internalLpArray[0].getBcArray();
119   - if (aBcArray.length % 2 != 0) { // 不能整除2,去除一个班次计算
120   - aBcArray.splice(aBcArray.length - 1, 1);
121   - }
122   - var sum = 0;
123   - // 加吃饭时间
124   - sum += _paramObj.fnGetLunchTime();
125   - sum += _paramObj.fnGetDinnerTime();
126   - // 加进出场时间
127   - sum += _qIsUp ? _paramObj.getUpOutTime() : _paramObj.getDownOutTime();
128   - sum += _qIsUp ? _paramObj.getDownInTime() : _paramObj.getUpInTime();
129   - // 例保时间
130   - //sum += _paramObj.getLbTime() * 2;
131   - for (i = 0; i < aBcArray.length; i++) {
132   - sum += aBcArray[i].getBcTime() + aBcArray[i].getStopTime();
133   - }
134   - for (i = 0; i < _aBxDesc.length; i++) {
135   - _aBxDesc[i].fAverTime = sum / (aBcArray.length / 2);
136   - _aBxDesc[i].fBcCount = ((_aBxDesc[i].fHoursV * 60) / _aBxDesc[i].fAverTime) * 2;
137   - }
138   -
139   - // 在第一个班次之前再添加一个模拟班次,用于中标线的作用
140   - // 那一圈必定是低谷,而且圈索引0,班次索引1,暂时标记,最后删除
141   - var iFirstStopTime =
142   - _paramObj.fnCalcuFixedStopNumber(
143   - _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -10),
144   - _qIsUp
145   - );
146   - var iXXTime = _qIsUp ? _paramObj.getDownTroughTime() : _paramObj.getUpTroughTime();
147   - var oFlagBc = _factory.createBcObj( // 标记班次
148   - _internalLpArray[0],
149   - "normal",
150   - !_qIsUp,
151   - 1,
152   - _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -(iFirstStopTime + iXXTime)),
153   - _paramObj
154   - );
155   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
156   -
157   - _internalLpArray[0].setBc(0, 1, oFlagBc);
158   -
159   - // 在最后一圈也补上一个或者2个模拟班次,暂时标记,最后需要删除
160   - var aMaxBcIndex = _internalLpArray[0].getMaxBcObjPosition();
161   - if (aMaxBcIndex[0] == _qCount - 1) { // 可能加半圈
162   - oFlagBc = _factory.createBcObj( // 标记班次
163   - _internalLpArray[0],
164   - "normal",
165   - !_qIsUp,
166   - 1,
167   - _paramObj.addMinute(
168   - _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
169   - _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
170   - _paramObj
171   - );
172   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
173   - _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
174   -
175   - } else { // 加完整的一圈
176   - oFlagBc = _factory.createBcObj( // 标记班次
177   - _internalLpArray[0],
178   - "normal",
179   - _qIsUp,
180   - 1,
181   - _paramObj.addMinute(
182   - _internalLpArray[0].getBc(_qCount - 2, 1).getArrTimeObj(),
183   - _internalLpArray[0].getBc(_qCount - 2, 1).getStopTime()),
184   - _paramObj
185   - );
186   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
187   - _internalLpArray[0].setBc(_qCount - 1, 0, oFlagBc);
188   -
189   - oFlagBc = _factory.createBcObj( // 标记班次
190   - _internalLpArray[0],
191   - "normal",
192   - !_qIsUp,
193   - 1,
194   - _paramObj.addMinute(
195   - _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
196   - _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
197   - _paramObj
198   - );
199   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
200   - _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
201   -
202   - }
203   -
204   - console.log("上行首班车时间:" + _paramObj.getUpFirstDTimeObj().format("HH:mm") +
205   - "上行末班车时间:" + _paramObj.getUpLastDtimeObj().format("HH:mm"));
206   - console.log("下行首班车时间:" + _paramObj.getDownFirstDTimeObj().format("HH:mm") +
207   - "下行末班车时间:" + _paramObj.getDownLastDTimeObj().format("HH:mm"));
208   - console.log("总共计算的圈数:" + _qCount);
209   - console.log("圈的方向isUP:" + _qIsUp);
210   - console.log("班型描述(以下):");
211   - console.log(_aBxDesc);
212   - console.log("所有路牌间隔描述(以下):");
213   - for (i = 0; i < _internalLpArray.length; i++) {
214   - console.log(_internalLpArray[i]._$_aVerticalIntervalTime);
215   - }
216   - console.log("//---------------- 行车计划,初始化方法1 end ----------------//");
217   -
218   - };
219   -
220   - //------------------ 初始化方法2,以及计算关联的内部变量 ----------------//
221   - var _approximate_zgfQIndex; // 预估早高峰车辆从第几圈开始全部发出
222   - var _approximate_zgfBIndex; // 预估早高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
223   - var _approximate_wgfQIndex; // 预估晚高峰车辆从第几圈开始全部发出
224   - var _approximate_wgfBIndex; // 预估晚高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
225   -
226   - var _fnInitFun2 = function() { // 初始化方法2
227   - console.log("//---------------- 行车计划,初始化方法2 start ----------------//");
228   -
229   - //------------------------ 1、计算车辆总数 ------------------------//
230   - // 是用高峰上行周转时间除以高峰平均间隔得到的
231   - // 这样算还算合理,车辆不多不少,待以后有新的算法再修正
232   - var iClCount = _paramObj.calcuClzx();
233   -
234   - //------------------------ 2、计算所有路牌的发车在各个圈中的间隔 --------------------//
235   - var i;
236   - var j;
237   - var iBindex = 1;
238   - var iZzsj;
239   - var oLp;
240   - var iC1;
241   - var iC2;
242   -
243   - for (i = 0; i < _qCount - 1; i++) {
244   - while (iBindex <= 1) {
245   - // 每圈每个方向的周转时间不一致,以上标线为主
246   - oLp = _internalLpArray[0];
247   - iZzsj = oLp.getBc(i + 1, iBindex).getFcTimeObj().diff(
248   - oLp.getBc(i, iBindex).getFcTimeObj(), "m"
249   - );
250   -
251   - iC1 = Math.floor(iZzsj / iClCount);
252   - iC2 = iZzsj % iClCount;
253   -
254   - for (j = 0; j < iClCount - iC2; j++) {
255   - oLp = _internalLpArray[j];
256   - oLp.fnSetVerticalIntervalTime(i, iBindex, iC1);
257   - }
258   -
259   - for (j = 0; j < iC2; j++) {
260   - oLp = _internalLpArray[iClCount - iC2 + j];
261   - oLp.fnSetVerticalIntervalTime(i, iBindex, iC1 + 1);
262   - }
263   -
264   - iBindex ++;
265   -
266   - }
267   - iBindex = 0;
268   - }
269   - // 最后一圈没有下一圈的参照,周转时间没发获取,由于都是低谷,所以使用倒数第二圈的间隔最为最后一圈的间隔
270   - for (i = 0; i < _internalLpArray.length; i++) {
271   - oLp = _internalLpArray[i];
272   - oLp.fnSetVerticalIntervalTime(_qCount - 1, 0, oLp.fnGetVerticalIntervalTime(_qCount - 2, 0));
273   - oLp.fnSetVerticalIntervalTime(_qCount - 1, 1, oLp.fnGetVerticalIntervalTime(_qCount - 2, 1));
274   - }
275   -
276   - //------------------------ 3、预估早高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
277   -
278   - // 以上标线为标准,查找离早高峰开始时间最近的班次作为早高峰开始班次
279   - // 以这个班次为早高峰起点,全部出车策略
280   - var qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
281   - _paramObj.getMPeakStartTimeObj(), true, true);
282   - var qIndex = qbcIndexArray[0]; // 第几圈
283   - var bIndex = qbcIndexArray[1]; // 第几个班次
284   -
285   - for (i = 1; i < _internalLpArray.length; i++) {
286   - _fnGenerateBcAndSetBc(i, qIndex, bIndex);
287   - }
288   -
289   - _approximate_zgfQIndex = qIndex;
290   - _approximate_zgfBIndex = bIndex;
291   -
292   - //------------------------ 4、预估晚高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
293   -
294   - // 以上标线为标准,查找离晚高峰开始时间最近的班次作为晚高峰开始班次
295   - // 以这个班次为早高峰起点,全部出车策略
296   - qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
297   - _paramObj.getEPeakStartTimeObj(), true, true);
298   - qIndex = qbcIndexArray[0]; // 第几圈
299   - bIndex = qbcIndexArray[1]; // 第几个班次
300   -
301   - for (i = 1; i < _internalLpArray.length; i++) {
302   - _fnGenerateBcAndSetBc(i, qIndex, bIndex);
303   - }
304   -
305   - _approximate_wgfQIndex = qIndex;
306   - _approximate_wgfBIndex = bIndex;
307   -
308   - console.log("早高峰周转时间(固定最大停战时间):" + _paramObj.calcuPeakZzsj() + "分钟");
309   - console.log("早高峰发车时间范围:" + _paramObj.getMPeakMinFcjx() + "分钟 --- " + _paramObj.getMPeakMaxFcjx() + "分钟");
310   - console.log("预估早高峰第" + _approximate_zgfQIndex + "(index)圈,第" + _approximate_zgfBIndex + "(index)班次车辆全部发出");
311   - console.log("预估晚高峰第" + _approximate_wgfQIndex + "(index)圈,第" + _approximate_wgfBIndex + "(index)班次车辆全部发出");
312   - console.log("//---------------- 行车计划,初始化方法2 end ----------------//");
313   - };
314   -
315   - //----------------------- 初始化方法3,计算连班分班的路牌分布 ----------------//
316   - var _iBx_lb_lpcount; // 连班路牌数
317   - var _iBx_5_2_fb_lpcount; // 5休2分班路牌数
318   - var _iBx_other_fb_lpcount; // 其他分班路牌数
319   -
320   - var _fnInitFun3 = function() { // 初始化方法3
321   - console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
322   -
323   - //--------------------- 1、计算分班连班班型车辆分布数 --------------------//
324   - // 总共车辆数(高峰最大车辆数)
325   - var iCls = _paramObj.calcuClzx();
326   - // 低谷最少配车(连班车数量)
327   - var iDgminpc = Math.round(_paramObj.calcuTroughZzsj() / _paramObj.getTroughMaxFcjx());
328   - // 加班车路牌数(做5休2的路牌数)
329   - var i_5_2_lpes = _paramObj.getJBLpes();
330   -
331   - // 做些简单的验证
332   - if (iCls < iDgminpc) {
333   - alert("总配车数小于低谷最小配车");
334   - throw "总配车数小于低谷最小配车";
335   - }
336   - if (iDgminpc < 2) {
337   - alert("连班路牌小于2,办不到啊");
338   - throw "连班路牌小于2,办不到啊";
339   - }
340   - if (iCls - iDgminpc < i_5_2_lpes) {
341   - alert("总分班路牌数小于加班路牌数");
342   - throw "总分班路牌数小于加班路牌数";
343   - }
344   -
345   - _iBx_lb_lpcount = iDgminpc;
346   - _iBx_5_2_fb_lpcount = i_5_2_lpes;
347   - _iBx_other_fb_lpcount = iCls - iDgminpc - i_5_2_lpes;
348   -
349   - //------------------------ 2、利用间隔法计算连班路牌分布 --------------------//
350   - var i;
351   - var j;
352   - var iC1 = Math.floor(_internalLpArray.length / _iBx_lb_lpcount);
353   - var iC2 = _internalLpArray.length % _iBx_lb_lpcount;
354   - var iLpIndex;
355   -
356   - for (i = 0; i < _iBx_lb_lpcount - iC2; i++) {
357   - iLpIndex = i * iC1;
358   - _internalLpArray[iLpIndex].setBxLb(true);
359   - _internalLpArray[iLpIndex].setBxDesc("连班");
360   - }
361   - for (j = 0; j < iC2; j++) {
362   - iLpIndex = i * iC1 + j * (iC1 + 1);
363   - _internalLpArray[iLpIndex].setBxLb(true);
364   - _internalLpArray[iLpIndex].setBxDesc("连班");
365   - }
366   -
367   - //------------------------ 3、利用间隔法计算分班班型路牌分布 --------------------//
368   - // 获取分班路牌索引
369   - var aNotLbIndexes = [];
370   - for (i = 0; i < _internalLpArray.length; i++) {
371   - if (!_internalLpArray[i].isBxLb()) {
372   - aNotLbIndexes.push(i);
373   - }
374   - }
375   - // 先5休2分班
376   - iC1 = Math.floor(aNotLbIndexes.length / _iBx_5_2_fb_lpcount);
377   - iC2 = aNotLbIndexes.length % _iBx_5_2_fb_lpcount;
378   -
379   - for (i = 0; i < _iBx_5_2_fb_lpcount - iC2; i++) {
380   - iLpIndex = aNotLbIndexes[i * iC1];
381   - _internalLpArray[iLpIndex].setBxLb(false);
382   - _internalLpArray[iLpIndex].setBxFb(true);
383   - _internalLpArray[iLpIndex].setBxFb5_2(true);
384   - _internalLpArray[iLpIndex].setBxDesc("5休2分班");
385   - }
386   - for (i = 0; i < iC2; i++) {
387   - iLpIndex = aNotLbIndexes[_iBx_lb_lpcount - iC2 + i * (iC1 + 1)];
388   - _internalLpArray[iLpIndex].setBxLb(false);
389   - _internalLpArray[iLpIndex].setBxFb(true);
390   - _internalLpArray[iLpIndex].setBxFb5_2(true);
391   - _internalLpArray[iLpIndex].setBxDesc("5休2分班");
392   - }
393   - // 其他分班
394   - for (i = 0; i < aNotLbIndexes.length; i++) {
395   - iLpIndex = aNotLbIndexes[i];
396   - if (!_internalLpArray[iLpIndex].isBxFb5_2()) {
397   - _internalLpArray[iLpIndex].setBxLb(false);
398   - _internalLpArray[iLpIndex].setBxFb(true);
399   - _internalLpArray[iLpIndex].setBxFb5_2(false);
400   - _internalLpArray[iLpIndex].setBxDesc("其他分班");
401   - }
402   - }
403   -
404   -
405   - console.log("连班路牌数:" + _iBx_lb_lpcount);
406   - console.log("5休2分班路牌数:" + _iBx_5_2_fb_lpcount);
407   - console.log("其他分班路牌数:" + _iBx_other_fb_lpcount);
408   - var aLbIndexes = [];
409   - for (i = 0; i < _internalLpArray.length; i++) {
410   - if (_internalLpArray[i].isBxLb()) {
411   - aLbIndexes.push(i);
412   - }
413   - }
414   - console.log("连班路牌indexes=" + aLbIndexes);
415   - var a_5_2_fbIndexes = [];
416   - for (i = 0; i < _internalLpArray.length; i++) {
417   - if (_internalLpArray[i].isBxFb() && _internalLpArray[i].isBxFb5_2()) {
418   - a_5_2_fbIndexes.push(i);
419   - }
420   - }
421   - console.log("5休2分班路牌indexes=" + a_5_2_fbIndexes);
422   - var a_other_fbIndexes = [];
423   - for (i = 0; i < _internalLpArray.length; i++) {
424   - if (_internalLpArray[i].isBxFb() && !_internalLpArray[i].isBxFb5_2()) {
425   - a_other_fbIndexes.push(i);
426   - }
427   - }
428   - console.log("其他分班路牌indexes=" + a_other_fbIndexes);
429   -
430   - console.log("//---------------- 行车计划,初始化方法3 end ----------------//");
431   - };
432   -
433   - //----------------------- 初始化方法4,计算中标线位置 -------------------------//
434   - var _iZbx_lpIndex; // 中标线对应第几个路牌
435   -
436   - var _fnInitFun4 = function() { // 初始化方法4
437   - console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
438   -
439   - //---------------------------- 1、模拟一个中标线,使用临时路牌 ----------------------//
440   - // 构造中标线
441   - // 中标线开始时间,就是方向的首班车时间
442   - var oSt = !_qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
443   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
444   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
445   - var oEt;
446   - if (_paramObj.getUpLastDtimeObj().isBefore(
447   - _paramObj.getDownLastDTimeObj())) {
448   - oEt = _paramObj.getDownLastDTimeObj();
449   - } else {
450   - oEt = _paramObj.getUpLastDtimeObj();
451   - }
452   -
453   - var oTempLp = new InternalLpObj({lpNo: -999, lpName: "-999"}, _qCount, _qIsUp);
454   - oTempLp.initDataFromTimeToTime(
455   - oSt,
456   - oEt,
457   - !_qIsUp,
458   - 0,
459   - _paramObj,
460   - _factory
461   - );
462   -
463   - //------------------------ 2、找出中标线的早高峰班次,计算应该插在当前路牌数组的那个位置 ----------------//
464   - // 找出中标线对应的早高峰的班次对象
465   - var oZb_gf_bc = oTempLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
466   -
467   - // 把所有连班路牌高峰班次重新构造成一个一个的圈数组,计算对应中标线最近的是第几个路牌
468   - // 中标线和上标线一样在连班路牌上
469   - var aTempq = [];
470   - var oTempq;
471   - var oTempb;
472   - var i;
473   - var oLp;
474   -
475   - var aLbIndexes = []; // 连班的路牌索引
476   - for (i = 0; i < _internalLpArray.length; i++) {
477   - if (_internalLpArray[i].isBxLb()) {
478   - aLbIndexes.push(i);
479   - }
480   - }
481   -
482   - for (i = 0; i < aLbIndexes.length; i++) {
483   - oLp = _internalLpArray[aLbIndexes[i]];
484   -
485   - oTempb = oLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
486   - if (oTempb.isUp() == _qIsUp) {
487   - oTempq = new InternalGroupObj(oLp, _qIsUp, oTempb, undefined);
488   - } else {
489   - oTempq = new InternalGroupObj(oLp, _qIsUp, undefined, oTempb);
490   - }
491   - aTempq.push(oTempq);
492   -
493   - }
494   -
495   - var aTtindex = oTempLp.getgetQBcIndexWithFcTimeFromGroupArray(
496   - oZb_gf_bc.getFcTimeObj(),
497   - aTempq,
498   - true,
499   - true
500   - );
501   -
502   - _iZbx_lpIndex = aLbIndexes[aTtindex[0]]; // 中标线放在第几个路牌
503   - oTempLp.setLp(_lpArray[_iZbx_lpIndex]); // 设置原始路牌对象
504   - oTempLp._$_aVerticalIntervalTime = _internalLpArray[_iZbx_lpIndex]._$_aVerticalIntervalTime; // 设置纵向最小发车间隔
505   - oTempLp.setBxLb(_internalLpArray[_iZbx_lpIndex].isBxLb());
506   - oTempLp.setBxFb(_internalLpArray[_iZbx_lpIndex].isBxFb());
507   - oTempLp.setBxFb5_2(_internalLpArray[_iZbx_lpIndex].isBxFb5_2());
508   -
509   - // 修正除了第一个班次外,其余其他班次
510   - var iBcindex = 0;
511   - for (i = 1; i < _qCount; i++) {
512   - while (iBcindex <= 1) {
513   - if (oTempLp.getBc(i, iBcindex)) { // 替换存在的班次
514   - oTempLp.setBc(i, iBcindex, _fnGenerateBc(_iZbx_lpIndex, i, iBcindex));
515   - }
516   - iBcindex ++;
517   - }
518   - iBcindex = 0;
519   - }
520   -
521   - _internalLpArray[_iZbx_lpIndex] = oTempLp;
522   -
523   - console.log("中标线对应第" + (_iZbx_lpIndex + 1) + "个路牌");
524   -
525   - console.log("//---------------- 行车计划,初始化方法4 end ----------------//");
526   - };
527   -
528   - //-------------------- 重要的内部方法 -----------------------//
529   - /**
530   - * 核心方法,利用路牌间隔纵向生成班次。
531   - * @param iLpindex 路牌索引
532   - * @param iQindex 圈索引
533   - * @param iBcindex 班次索引
534   - * @returns object InternalBcObj,失败 false
535   - */
536   - var _fnGenerateBc = function(iLpindex, iQindex, iBcindex) {
537   - // 以上标线为起始点,使用路牌在不同圈,班次索引的发车间隔,计算班次
538   - // 注意,发车间隔是指下一个班次应该距离当前班次间隔,是从下往上的
539   -
540   - // 1、参数验证
541   - if (iLpindex == 0) { // 上标线的班次不需要生成
542   - return false;
543   - }
544   -
545   - // 2、计算间隔
546   - var i;
547   - var oLp;
548   - var iTime = 0;
549   - for (i = 0; i < iLpindex; i++) {
550   - oLp = _internalLpArray[i];
551   - iTime += oLp.fnGetVerticalIntervalTime(iQindex, iBcindex);
552   - }
553   -
554   - // 3、生成班次
555   - var _oKsbc = _internalLpArray[0].getBc(iQindex, iBcindex);
556   - if (!_oKsbc) {
557   - return false;
558   - }
559   - var _oKssj = _paramObj.addMinute(_oKsbc.getFcTimeObj(), iTime);
560   - var _oBc = _factory.createBcObj(
561   - _internalLpArray[iLpindex],
562   - "normal", _oKsbc.isUp(),
563   - 1, _oKssj, _paramObj);
564   -
565   - return _oBc;
566   -
567   - };
568   -
569   - /**
570   - * 核心方法,在指定位置生成班次并添加到路牌指定位置中。
571   - * @param lpIndex 第几个路牌
572   - * @param qIndex 第几圈
573   - * @param bcIndex 第几个班次
574   - */
575   - var _fnGenerateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
576   - var _bcObj = _fnGenerateBc(lpIndex, qIndex, bcIndex);
577   - if (_bcObj) {
578   - _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
579   - }
580   - };
581   -
582   -
583   - /**
584   - * 在指定位置生成班次(内部重要方法)。
585   - * @param lpIndex 第几个路牌
586   - * @param qIndex 第几圈
587   - * @param bcIndex 第几个班次
588   - * @returns InternalBcObj
589   - */
590   - var _generateBc = function(lpIndex, qIndex, bcIndex) {
591   - // 在初始化布局后使用,否则没有参照班次加不了
592   - // 初始化布局后,相当于把时刻表比作一个围棋棋盘,行为路牌数,列为圈数
593   - // 上标线,中标线,早晚高峰已经布局在棋盘上,其余的空格可以创建班次
594   -
595   - // 这个生成班次是以上一班次时间,以发车间隔为基础添加的,纵向加
596   - // 和生成标线时那种一直往后加班次时不一样,那种是以前一个班次为基础,横向加
597   -
598   - // 1、生成的班次以同一圈同一个方向里离它最早的班次的发车时间为基础
599   - // 2、以每个路牌的纵向最小发车间隔时间为计算发车间隔
600   - // 3、如果班次发车时间越界不管,有其余方法排除这种情况
601   -
602   - // 1、查找同圈同方向里最近的班次,找不到报错(因为有标线存在是不可能找不到的)
603   - var _i;
604   - var _bcObj;
605   - for (_i = lpIndex - 1; _i >= 0; _i--) {
606   - _bcObj = _internalLpArray[_i].getBc(qIndex, bcIndex);
607   - if (_bcObj) {
608   - break;
609   - }
610   - }
611   - if (!_bcObj) {
612   - return false;
613   - //alert("无法在指定位置生成班次");
614   - //throw "无法在路牌index=" + lpIndex + ",圈index=" + qIndex + ",班次index=" + bcIndex + "生成班次";
615   - }
616   -
617   - // 2、计算发车间隔
618   - var _intervalTime = 0;
619   - for (_i = _i + 1; _i <= lpIndex; _i++) {
620   - _intervalTime += _internalLpArray[_i].getVerticalMinIntervalTime();
621   - }
622   -
623   - // 3、计算班次并添加班次
624   - var _kssj = _paramObj.addMinute(_bcObj.getFcTimeObj(), _intervalTime);
625   - _bcObj = _factory.createBcObj(
626   - _internalLpArray[lpIndex],
627   - "normal", _bcObj.isUp(),
628   - 1, _kssj, _paramObj);
629   - _bcObj.setGroup(_internalLpArray[lpIndex].getGroup(qIndex));
630   -
631   - return _bcObj;
632   -
633   - // TODO:这种添加班次的方法,可能造成相邻班次的停站时间问题
634   - // TODO:主要是由于中标线的问题,但是误差不会很大,
635   - // TODO:后面有方法直接调整停站时间(所谓的平滑过度时间)
636   - };
637   -
638   - /**
639   - * 在指定位置生成班次并添加到路牌指定位置中。
640   - * @param lpIndex 第几个路牌
641   - * @param qIndex 第几圈
642   - * @param bcIndex 第几个班次
643   - */
644   - var _generateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
645   - var _bcObj = _generateBc(lpIndex, qIndex, bcIndex);
646   - _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
647   -
648   - };
649   -
650   - /**
651   - * 查找离指定时间最近的前面的班次索引信息
652   - * @param timeObj 查找时间
653   - * @param isUp 是否上行
654   - * @returns [{路牌index},{圈index},{班次index}]
655   - */
656   - var _findUpClosedBcIndexWithTime = function(timeObj, isUp) {
657   -
658   - // dododo
659   -
660   - var _lpObj;
661   - var _groupObj;
662   - var _bcObj;
663   - var _i;
664   - var _j;
665   - var timediff; // 时间差取绝对值
666   -
667   - var _lpIndex;
668   - var _up_qIndex;
669   - var _up_bIndex;
670   -
671   - for (_i = 0; _i < _qCount; _i++) {
672   - for (_j = 0; _j < _internalLpArray.length; _j++) {
673   - _lpObj = _internalLpArray[_j];
674   - _groupObj = _lpObj.getGroup(_i);
675   - _bcObj = isUp ? _groupObj.getBc1() : _groupObj.getBc2();
676   - if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
677   - _bcObj = _generateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
678   - }
679   - if (_bcObj) {
680   - if (timeObj.diff(_bcObj.getFcTimeObj()) >= 0) {
681   - if (!timediff) {
682   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
683   - _lpIndex = _j;
684   - _up_qIndex = _i;
685   - _up_bIndex = isUp == _qIsUp ? 0 : 1;
686   - } else {
687   - if (timeObj.diff(_bcObj.getFcTimeObj()) < timediff) {
688   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
689   - _lpIndex = _j;
690   - _up_qIndex = _i;
691   - _up_bIndex = isUp == _qIsUp ? 0 : 1;
692   - }
693   - }
694   - }
695   - }
696   - }
697   - }
698   -
699   - if (_lpIndex == undefined) {
700   - return false;
701   - }
702   -
703   - var bcindex = [];
704   - bcindex.push(_lpIndex);
705   - bcindex.push(_up_qIndex);
706   - bcindex.push(_up_bIndex);
707   -
708   - return bcindex;
709   - };
710   -
711   - /**
712   - * 查找离指定时间最近的后面的班次索引信息
713   - * @param timeObj 查找时间
714   - * @param isUp 是否上行
715   - * @returns [{路牌index},{圈index},{班次index}]
716   - */
717   - var _findDownClosedBcIndexWithTime = function(timeObj, isUp) {
718   - var _lpObj;
719   - var _groupObj;
720   - var _bcObj;
721   - var _i;
722   - var _j;
723   - var timediff; // 时间差取绝对值
724   -
725   - var _lpIndex;
726   - var _down_qIndex;
727   - var _down_bIndex;
728   -
729   - var flag;
730   -
731   - for (_i = 0; _i < _qCount; _i++) {
732   - for (_j = 0; _j < _internalLpArray.length; _j++) {
733   - _lpObj = _internalLpArray[_j];
734   - _groupObj = _lpObj.getGroup(_i);
735   - _bcObj = isUp ? _groupObj.getBc1() : _groupObj.getBc2();
736   - if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
737   - _bcObj = _generateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
738   - }
739   - if (_bcObj) {
740   - //console.log("timeobj -> bcobj diff flag " +
741   - // timeObj.format("HH:mm") + "->" +
742   - // _bcObj.getFcTimeObj().format("HH:mm") +
743   - // timeObj.diff(_bcObj.getFcTimeObj()) +
744   - // (timeObj.diff(_bcObj.getFcTimeObj()) <= 0)
745   - //);
746   -
747   - flag = (timeObj.diff(_bcObj.getFcTimeObj())) <= 0;
748   -
749   - if (flag) {
750   - if (!timediff) {
751   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
752   - _lpIndex = _j;
753   - _down_qIndex = _i;
754   - _down_bIndex = isUp == _qIsUp ? 0 : 1;
755   - } else {
756   - if ((timeObj.diff(_bcObj.getFcTimeObj())) > timediff) {
757   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
758   - _lpIndex = _j;
759   - _down_qIndex = _i;
760   - _down_bIndex = isUp == _qIsUp ? 0 : 1;
761   - }
762   - }
763   - }
764   - }
765   - }
766   - }
767   -
768   - if (_lpIndex == undefined) {
769   - return false;
770   - }
771   -
772   - var bcindex = [];
773   - bcindex.push(_lpIndex);
774   - bcindex.push(_down_qIndex);
775   - bcindex.push(_down_bIndex);
776   -
777   - return bcindex;
778   - };
779   -
780   - return {
781   - //------------- 布局初始化方法 ------------//
782   - /**
783   - * 初始化数据,使用标线初始化
784   - */
785   - fnInitDataWithBxLayout: function() {
786   - // 初始化布局1,构造上标线,计算圈数,把上标线数据放入第一个路牌中
787   - _fnInitFun1();
788   - // 初始化布局2,从上标线的某个班次开始,构造所有路牌的早高峰班次,晚高峰班次,计算路牌在各个圈中的间隔
789   - _fnInitFun2();
790   - // 初始化布局3,计算连班分班路牌分布
791   - _fnInitFun3();
792   - // 初始化布局4,计算中标线位置
793   - _fnInitFun4();
794   -
795   - },
796   -
797   - /**
798   - * 调整高峰班次,
799   - * 初始化生成早高峰,晚高峰班次并不准确,因为根据高峰时间段,并不在一个完整圈内,应该是在两个或多个圈之间
800   - * 当初始化定好布局后(上标线,中标线),然后确定每个路牌的班型(连班,分班,5休2分班)后
801   - * 然后重新计算框在高峰时间段内的班次索引,不足的添加,之前多加的删除(只删除分班路牌上的)
802   - * @param isZgf 是否早高峰
803   - * @param isUp 是否上行
804   - */
805   - fnAdjustGfbc : function(isZgf, isUp) {
806   - var oStartTime; // 开始时间
807   - var oEndTime; // 结束时间
808   - var iStartBcIndex; // 开始班次索引
809   - var iEndBcIndex; // 结束班次索引
810   -
811   - oStartTime = isZgf ? _paramObj.getMPeakStartTimeObj() : _paramObj.getEPeakStartTimeObj();
812   - oEndTime = isZgf ? _paramObj.getMPeakEndTimeObj() : _paramObj.getEPeakEndTimeObj();
813   -
814   - aStartBcIndex = _findUpClosedBcIndexWithTime(oStartTime, isUp);
815   - aEndBcIndex = _findDownClosedBcIndexWithTime(oEndTime, isUp);
816   -
817   - var iLpIndex;
818   - var iQIndex;
819   - var iBcIndex;
820   - var iQInternelCount; // 高峰时间段中间包含的圈数
821   - var i;
822   - var j;
823   -
824   - var oLp;
825   -
826   - if (aStartBcIndex && aEndBcIndex) {
827   - iLpIndex = aStartBcIndex[0];
828   - iQIndex = aStartBcIndex[1];
829   - iBcIndex = aStartBcIndex[2];
830   -
831   - // 处理头
832   - // 删除头部多余班次
833   - for (j = 0; j < iLpIndex; j++) {
834   - oLp = _internalLpArray[j];
835   - if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
836   - oLp.removeBc(iQIndex, iBcIndex);
837   - }
838   - }
839   -
840   - for (j = iLpIndex; j < _internalLpArray.length; j++) {
841   - oLp = _internalLpArray[j];
842   - if (!oLp.getBc(iQIndex, iBcIndex)) {
843   - _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
844   - }
845   - }
846   -
847   - // 处理中间
848   - iQInternelCount = aEndBcIndex[1] - aStartBcIndex[1] - 1;
849   - for (i = 1; i <= iQInternelCount; i++) {
850   - oLp = _internalLpArray[iQIndex + i];
851   - if (!oLp.getBc(iQIndex + i, iBcIndex)) {
852   - _fnGenerateBcAndSetBc(i, iQIndex + i, iBcIndex);
853   - }
854   - }
855   -
856   - // 处理尾部
857   - iLpIndex = aEndBcIndex[0];
858   - iQIndex = aEndBcIndex[1];
859   - iBcIndex = aEndBcIndex[2];
860   -
861   - // 删除尾部多余的班次
862   - for (j = iLpIndex; j < _internalLpArray.length; j++) {
863   - oLp = _internalLpArray[j];
864   - if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
865   - oLp.removeBc(iQIndex, iBcIndex);
866   - }
867   - }
868   -
869   - if (aStartBcIndex[1] != aEndBcIndex[1]) { // 指定时间范围跨圈
870   - for (j = 0; j < iLpIndex; j++) {
871   - oLp = _internalLpArray[j];
872   - if (!oLp.getBc(iQIndex, iBcIndex)) {
873   - _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
874   - }
875   - }
876   - } else {
877   - // 不跨圈,不用处理,处理头的时候已经加了
878   - }
879   -
880   - }
881   -
882   - },
883   -
884   - /**
885   - * 按照营运时间要求补充班次,
886   - * 早高峰7:45分以前出场运营,
887   - * 晚高峰16:10分以前出场运营
888   - */
889   - fnCalcuLpBc_yy: function() {
890   - // 补班次的时候,针对的是分班班型
891   - var i;
892   - var _oLp;
893   - var _oBc;
894   - var _aMinBcIndex;
895   - var _aMaxBcIndex;
896   -
897   - var _qIndex;
898   - var _bIndex;
899   -
900   - var _zgfCDate = _paramObj.toTimeObj("7:45");
901   - var _wgfCDate = _paramObj.toTimeObj("16:10");
902   - var _ccsj;
903   -
904   - for (i = 0; i < _internalLpArray.length; i++) {
905   - _oLp = _internalLpArray[i];
906   - if (_oLp.isBxFb()) { // 分班路牌
907   - // 早高峰部分
908   - _aMinBcIndex = _oLp.getMinBcObjPosition();
909   - _qIndex = _aMinBcIndex[0];
910   - _bIndex = _aMinBcIndex[1];
911   - _oBc = _oLp.getBc(_qIndex, _bIndex);
912   - if (_qIsUp) {
913   - _ccsj = _bIndex == 0 ?
914   - _paramObj.getUpOutTime() :
915   - _paramObj.getDownOutTime();
916   - } else {
917   - _ccsj = _bIndex == 0 ?
918   - _paramObj.getDownOutTime() :
919   - _paramObj.getUpOutTime();
920   - }
921   - if (_zgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
922   - _fnGenerateBcAndSetBc(
923   - i,
924   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
925   - _bIndex == 0 ? 1 : 0
926   - )
927   - }
928   -
929   - // 晚高峰部分
930   - _aMaxBcIndex = _oLp.getMaxBcObjPosition();
931   - _qIndex = _aMaxBcIndex[0];
932   - _bIndex = _aMaxBcIndex[1];
933   - _oBc = _oLp.getBc(
934   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
935   - _bIndex == 0 ? 1 : 0
936   - );
937   - if (!_oBc) { // 前一个班次不存在,再判定加不加
938   - _oBc = _oLp.getBc(_qIndex, _bIndex);
939   - if (_qIsUp) {
940   - _ccsj = _bIndex == 0 ?
941   - _paramObj.getUpOutTime() :
942   - _paramObj.getDownOutTime();
943   - } else {
944   - _ccsj = _bIndex == 0 ?
945   - _paramObj.getDownOutTime() :
946   - _paramObj.getUpOutTime();
947   - }
948   - if (_wgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
949   - _fnGenerateBcAndSetBc(
950   - i,
951   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
952   - _bIndex == 0 ? 1 : 0
953   - )
954   - }
955   - }
956   - }
957   - }
958   - },
959   -
960   - /**
961   - * 补充做5休2的班型班次。
962   - * 1、确认5_2班型大致多少圈(小数点过.7进位)
963   - * 2、获取当前5_2两端车次链的信息,每段的班次数目,还差几个班次没加
964   - * 3、如果前面的车次链班次少,则从前面的车次链开始加
965   - * 4、如果车次链班次数一样,从从后面的车次链开始加
966   - * 5、加班次时都是往车次链前方加
967   - * 6、如果前面车次链不能再加班次了,从后面车次链加
968   - */
969   - fnCalcuLpBx_5_2: function() {
970   - // 计算做5休2班型所需的班次数
971   - var iBxBcount = _aBxDesc[6].fBcCount;
972   - if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
973   - iBxBcount = Math.floor(iBxBcount) + 1;
974   - } else {
975   - iBxBcount = Math.floor(iBxBcount);
976   - }
977   -
978   - var i;
979   - var j;
980   - var oLp;
981   - var iAddBcCount;
982   - var oBcChain1;
983   - var oBcChain2;
984   - var iQindex;
985   - var iBindex;
986   -
987   - for (i = 0; i < _internalLpArray.length; i++) {
988   - oLp = _internalLpArray[i];
989   - if (oLp.isBxFb5_2()) {
990   - iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
991   - for (j = 1; j <= iAddBcCount; j++) {
992   - oBcChain1 = oLp.fnGetBcChainInfo(0);
993   - oBcChain2 = oLp.fnGetBcChainInfo(1);
994   -
995   - if (oBcChain1.bcount < oBcChain2.bcount) {
996   - iQindex = oBcChain1.s_b == 0 ? oBcChain1.s_q - 1 : oBcChain1.s_q;
997   - iBindex = oBcChain1.s_b == 0 ? 1 : 0;
998   - // 往车次链往前不能加,就往后加
999   - if (_fnGenerateBc(i, iQindex, iBindex)) {
1000   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1001   - } else {
1002   - iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
1003   - iBindex = oBcChain1.e_b == 0 ? 1 : 0;
1004   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1005   - }
1006   -
1007   - } else if (oBcChain1.bcount > oBcChain2.bcount) {
1008   - iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
1009   - iBindex = oBcChain2.s_b == 0 ? 1 : 0;
1010   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1011   - } else {
1012   - iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
1013   - iBindex = oBcChain2.s_b == 0 ? 1 : 0;
1014   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1015   - }
1016   - }
1017   - }
1018   - }
1019   -
1020   - },
1021   -
1022   - /**
1023   - * 补其他分班班型班次。
1024   - * 从车次链的后面开始加
1025   - */
1026   - fnCalcuLpBx_other: function() {
1027   - // TODO:暂时使用做2休1的班型
1028   - // 计算做5休2班型所需的班次数
1029   - var iBxBcount = _aBxDesc[4].fBcCount;
1030   - if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
1031   - iBxBcount = Math.floor(iBxBcount) + 1;
1032   - } else {
1033   - iBxBcount = Math.floor(iBxBcount);
1034   - }
1035   -
1036   - var i;
1037   - var j;
1038   - var oLp;
1039   - var iAddBcCount;
1040   - var oBcChain1;
1041   - var oBcChain2;
1042   - var iQindex;
1043   - var iBindex;
1044   -
1045   - for (i = 0; i < _internalLpArray.length; i++) {
1046   - oLp = _internalLpArray[i];
1047   - if (oLp.isBxFb() && !oLp.isBxFb5_2()) {
1048   - iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
1049   - for (j = 1; j <= iAddBcCount; j++) {
1050   - oBcChain1 = oLp.fnGetBcChainInfo(0);
1051   - oBcChain2 = oLp.fnGetBcChainInfo(1);
1052   -
1053   - if (oBcChain1.bcount < oBcChain2.bcount) {
1054   - iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
1055   - iBindex = oBcChain1.e_b == 0 ? 1 : 0;
1056   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1057   - } else if (oBcChain1.bcount > oBcChain2.bcount) {
1058   - iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
1059   - iBindex = oBcChain2.e_b == 0 ? 1 : 0;
1060   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1061   - } else {
1062   - iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
1063   - iBindex = oBcChain2.e_b == 0 ? 1 : 0;
1064   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1065   - }
1066   - }
1067   - }
1068   - }
1069   -
1070   - },
1071   -
1072   - /**
1073   - * 补充连班路牌班次。
1074   - * 1、上标线,中标线中间的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向上标线起始班次靠拢
1075   - * 2、中标线以下的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向中标线起始班次靠拢
1076   - */
1077   - fnCalcuLpBx_lb: function() {
1078   - // 补充连班的班次,参照上标线,中标线补充不足的班次
1079   -
1080   - var aLbLpindexes = []; // 除上标线,中标线的连班路牌索引
1081   - var i;
1082   - for (i = 0; i < _internalLpArray.length; i++) {
1083   - if (_internalLpArray[i].isBxLb() && i != 0 && i != _iZbx_lpIndex) {
1084   - aLbLpindexes.push(i);
1085   - }
1086   - }
1087   -
1088   - var oEndsj = // 结束时间
1089   - _paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj()) ?
1090   - _paramObj.getDownLastDTimeObj() :
1091   - _paramObj.getUpLastDtimeObj();
1092   -
1093   - var oLp;
1094   - var aMinbcPos;
1095   - var oBc;
1096   - var j;
1097   - var iTempBcIndex;
1098   -
1099   - // 1、从最小班次开始,往后补充班次
1100   - for (i = 0; i < aLbLpindexes.length; i++) {
1101   - oLp = _internalLpArray[aLbLpindexes[i]];
1102   -
1103   - // 最小班次索引
1104   - aMinbcPos = oLp.getMinBcObjPosition();
1105   - // 使用纵向分隔补充班次,从最小班次向后补
1106   - iTempBcIndex = aMinbcPos[1] == 0 ? 1 : 0;
1107   - j = iTempBcIndex == 0 ? aMinbcPos[0] + 1 : aMinbcPos[0];
1108   -
1109   - while (j < _qCount) {
1110   - while (iTempBcIndex <= 1) {
1111   - oBc = _fnGenerateBc(aLbLpindexes[i], j, iTempBcIndex);
1112   - if (oBc &&
1113   - oBc.getFcTimeObj().isBefore(oEndsj) &&
1114   - oBc.getArrTimeObj().isBefore(oEndsj)) {
1115   - oLp.setBc(j, iTempBcIndex, oBc);
1116   - }
1117   - iTempBcIndex++;
1118   - }
1119   - iTempBcIndex = 0;
1120   - j++;
1121   - }
1122   -
1123   - }
1124   -
1125   - // 2、上标线中标线之间的路牌,从最小的班次往前补充班次
1126   -
1127   - // 还要补充缺失的班次,差上标线几个班次要往前补上
1128   - var iBccount;
1129   - var iQindex;
1130   - var iBindex;
1131   - // 补上标线到中标线之间的连班路牌的班次
1132   - for (i = 0; i < aLbLpindexes.length; i++) {
1133   - if (aLbLpindexes[i] > 0 && aLbLpindexes[i] < _iZbx_lpIndex) {
1134   - oLp = _internalLpArray[aLbLpindexes[i]];
1135   - aMinbcPos = oLp.getMinBcObjPosition();
1136   - iQindex = aMinbcPos[0];
1137   - iBindex = aMinbcPos[1];
1138   - iBccount = (iQindex - 1) * 2 + iBindex; // 距离上标线起始站点差几个班次
1139   - for (j = 0; j < iBccount; j++) {
1140   - if (iBindex == 0) {
1141   - iQindex --;
1142   - iBindex = 1;
1143   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1144   - } else if (iBindex == 1) {
1145   - iBindex --;
1146   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1147   - }
1148   - }
1149   -
1150   - }
1151   -
1152   - }
1153   -
1154   - // 3、中标线之后的路牌,从最小的班次往前补充班次
1155   -
1156   - // 补中标线以下的连班路牌的班次
1157   - for (i = 0; i < aLbLpindexes.length; i++) {
1158   - if (aLbLpindexes[i] > _iZbx_lpIndex) {
1159   - oLp = _internalLpArray[aLbLpindexes[i]];
1160   - aMinbcPos = oLp.getMinBcObjPosition();
1161   - iQindex = aMinbcPos[0];
1162   - iBindex = aMinbcPos[1];
1163   - iBccount = (iQindex - 0) * 2 + iBindex - 1; // 距离上标线起始站点差几个班次
1164   - for (j = 0; j < iBccount; j++) {
1165   - if (iBindex == 0) {
1166   - iQindex --;
1167   - iBindex = 1;
1168   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1169   - } else if (iBindex == 1) {
1170   - iBindex --;
1171   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1172   - }
1173   - }
1174   - }
1175   - }
1176   -
1177   - },
1178   -
1179   - /**
1180   - * 计算末班车(一般都落在连班班型上,因为按照现在的布局方法,分班路牌不会一直连到最后)。
1181   - * 1、确定末班车早的班次
1182   - * 2、从后往前找到与这个班次最匹配的班次的位置(第几个路牌,第几圈,第几个班次),然后覆盖
1183   - * 3、从第2步找的位置,往上找与另一个末班车匹配的班次位置,然后覆盖
1184   - */
1185   - fnCalcuLastBc: function() {
1186   - //-------------------- 1、确定末班车早的方向,时间 -----------------------//
1187   - var _oLastTime;
1188   - var _bLastIsUp;
1189   - if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
1190   - _oLastTime = _paramObj.getUpLastDtimeObj();
1191   - _bLastIsUp = true;
1192   - } else {
1193   - _oLastTime = _paramObj.getDownLastDTimeObj();
1194   - _bLastIsUp = false;
1195   - }
1196   -
1197   - //-------------------- 2、确定比 _oLastTime 小或者等于的班次位置,并修改班次时间到末班车时间 -----------------//
1198   - var i;
1199   - var j;
1200   - var _oBc;
1201   - var _oLp;
1202   - var _aBcIndex;
1203   -
1204   - for (i = _qCount - 1; i >= 0; i--) {
1205   - if (_aBcIndex) {
1206   - break;
1207   - }
1208   - // 从大到小找到第一个合适的班次索引
1209   - for (j = _internalLpArray.length - 1; j >= 0; j--) {
1210   - _oLp = _internalLpArray[j];
1211   - if (_oLp.isBxLb()) {
1212   - _oBc = _oLp.getBc(i, _qIsUp == _bLastIsUp ? 0 : 1);
1213   - }
1214   - if (_oBc != undefined && _oBc.getFcTimeObj().isBefore(_oLastTime)) {
1215   - _aBcIndex = [];
1216   - _aBcIndex.push(j); // 路牌索引
1217   - _aBcIndex.push(i); // 圈索引
1218   - _aBcIndex.push(_qIsUp == _bLastIsUp ? 0 : 1); // 班次索引
1219   - break;
1220   - }
1221   - }
1222   - }
1223   -
1224   - //-------------------- 3、预估哪个个班次离末班最近,用末班替换,并删除后面的多余班次 -----------------//
1225   - // 第2步找到的班次不一定是最适合的,需要把之后的班次模拟出来再比较一下
1226   - var _aBcIndexes = []; // 里面放对象 {lpIndex,qIndex,bcIndex,fcsjTime}
1227   - _oBc = undefined;
1228   - for (i = _aBcIndex[0]; i < _internalLpArray.length; i++) {
1229   - _oLp = _internalLpArray[i];
1230   - if (_oLp.isBxLb()) {
1231   - _oBc = _oLp.getBc(_aBcIndex[1], _aBcIndex[2]);
1232   - if (_oBc == undefined) {
1233   - _oBc = _fnGenerateBc(i, _aBcIndex[1], _aBcIndex[2]);
1234   - }
1235   - _aBcIndexes.push({
1236   - lpIndex: i,
1237   - qIndex: _aBcIndex[1],
1238   - bcIndex: _aBcIndex[2],
1239   - bcObj: _oBc
1240   - })
1241   - }
1242   - }
1243   - var _oBcIndex_find; // 第几个路牌离末班车最近
1244   - for (i = _aBcIndexes.length - 1; i >= 0; i--) {
1245   - if (_aBcIndexes[i].bcObj.getFcTimeObj().isBefore(_oLastTime)) {
1246   - _oBcIndex_find = _aBcIndexes[i];
1247   - break;
1248   - }
1249   - }
1250   - // 替换成末班车
1251   - _oBc = _oBcIndex_find.bcObj;
1252   - _oBc.addMinuteToFcsj(_oLastTime.diff(_oBc.getFcTimeObj(), "m"));
1253   - _internalLpArray[_oBcIndex_find.lpIndex].setBc(
1254   - _oBcIndex_find.qIndex, _oBcIndex_find.bcIndex, _oBc
1255   - );
1256   -
1257   - // 删除多余班次呢
1258   - for (i = _oBcIndex_find.lpIndex + 1; i < _internalLpArray.length; i++) {
1259   - _internalLpArray[i].removeBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex);
1260   - }
1261   -
1262   - //---------------------- 4、从第3步找到的位置,开始往上找,确定另一个末班车,并删除后面多余的班次 -------------//
1263   - // 因为另一个末班车时间晚,肯定在后面,并且必须在之前的路牌
1264   - // 如果在之后的路牌,则意味着之前那个末班车位置不对,连班连起来会有两个之前的末班车
1265   - // 计算大的末班车时间
1266   - if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
1267   - _oLastTime = _paramObj.getDownLastDTimeObj();
1268   - _bLastIsUp = false;
1269   - } else {
1270   - _oLastTime = _paramObj.getUpLastDtimeObj();
1271   - _bLastIsUp = true;
1272   - }
1273   - _aBcIndexes = [];
1274   - for (i = _oBcIndex_find.lpIndex; i >=0; i--) {
1275   - _oLp = _internalLpArray[i];
1276   - if (_oLp.isBxLb()) {
1277   - _oBc = _oLp.getBc(
1278   - _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
1279   - _oBcIndex_find.bcIndex == 0 ? 1 : 0
1280   - );
1281   - if (_oBc == undefined) {
1282   - _oBc = _fnGenerateBc(
1283   - i,
1284   - _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
1285   - _oBcIndex_find.bcIndex == 0 ? 1 : 0
1286   - );
1287   - }
1288   - if (!_oBc) { // 纵向生成班次失败,用横向生成班次,发车时间取前一班次的到达时间加停战时间
1289   - _oBc = _factory.createBcObj(
1290   - _oLp,
1291   - "normal",
1292   - _bLastIsUp,
1293   - 3,
1294   - _oLp.getBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex).getArrTimeObj(),
1295   - _paramObj
1296   - );
1297   -
1298   - }
1299   - _aBcIndexes.push({
1300   - lpIndex: i,
1301   - qIndex: _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
1302   - bcIndex: _oBcIndex_find.bcIndex == 0 ? 1 : 0,
1303   - bcObj: _oBc
1304   - })
1305   - }
1306   - }
1307   -
1308   - console.log(_aBcIndexes);
1309   -
1310   - _oBcIndex_find = _aBcIndexes[0];
1311   -
1312   - for (i = 0; i < _aBcIndexes.length; i++) {
1313   - if (_aBcIndexes[i].bcObj.getFcTimeObj().isBefore(_oLastTime)) {
1314   - _oBcIndex_find = _aBcIndexes[i];
1315   - break;
1316   - }
1317   - }
1318   - // 替换成末班车
1319   - _oBc = _oBcIndex_find.bcObj;
1320   - _oBc.addMinuteToFcsj(_oLastTime.diff(_oBc.getFcTimeObj(), "m"));
1321   - _internalLpArray[_oBcIndex_find.lpIndex].setBc(
1322   - _oBcIndex_find.qIndex, _oBcIndex_find.bcIndex, _oBc
1323   - );
1324   -
1325   - // 删除多余班次呢
1326   - for (i = _oBcIndex_find.lpIndex + 1; i < _internalLpArray.length; i++) {
1327   - _internalLpArray[i].removeBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex);
1328   - }
1329   -
1330   -
1331   - },
1332   -
1333   - /**
1334   - * 添加吃饭班次。
1335   - */
1336   - fnCalcuEatBc: function() {
1337   - // 吃午饭时间范围,10:15 到 12:15
1338   - // 吃晚饭时间范围,18:00 到 19:00
1339   -
1340   - if (!_paramObj.fnIsEat()) {
1341   - return;
1342   - }
1343   -
1344   - // 午饭index
1345   - var aLEIndex;
1346   - // 晚饭index
1347   - var aDEIndex;
1348   -
1349   - // 所有吃饭都默认在一个方向,两个方向暂时不考虑
1350   - if (_paramObj.fnIsUpEat()) {
1351   - aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), true, false);
1352   - aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), true, false);
1353   - } else {
1354   - aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), false, true);
1355   - aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), false, true);
1356   - }
1357   -
1358   - // 午饭第几圈,第几个班次
1359   - var iLEQIndex = aLEIndex[0];
1360   - var iLEBIndex = aLEIndex[1];
1361   - // 晚饭第几圈,第几个班次
1362   - var iDEQIndex = aDEIndex[0];
1363   - var iDEBIndex = aDEIndex[1];
1364   -
1365   - // 注意,本模型只有连班才有吃饭
1366   -
1367   - var i;
1368   - var oLp;
1369   - var aLbIndex = []; // 连班班型的路牌索引
1370   - for (i = 0; i < _internalLpArray.length; i++) {
1371   - oLp = _internalLpArray[i];
1372   - if (oLp.isBxLb()) {
1373   - aLbIndex.push(i);
1374   - }
1375   - }
1376   -
1377   - var iLTime;
1378   - var iDtime;
1379   - var j;
1380   - for (i = 0; i < aLbIndex.length; i++) {
1381   - oLp = _internalLpArray[aLbIndex[i]];
1382   -
1383   - // 午饭
1384   - iLTime = oLp.fnAddEatBc(iLEQIndex, iLEBIndex, _factory, _paramObj);
1385   - // 晚饭
1386   - iDtime = oLp.fnAddEatBc(iDEQIndex, iDEBIndex, _factory, _paramObj);
1387   -
1388   - if (i == aLbIndex.length - 1) {
1389   - for (j = aLbIndex[i]; j < _internalLpArray.length; j++) {
1390   - oLp = _internalLpArray[j];
1391   - if (oLp.isBxFb()) { // 5休2班型不调整
1392   - // 修正午饭之后路牌班次的发车时间
1393   - oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
1394   - oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
1395   - }
1396   - }
1397   - } else {
1398   - for (j = aLbIndex[i]; j < aLbIndex[i + 1]; j++) {
1399   - oLp = _internalLpArray[j];
1400   - if (oLp.isBxFb()) {
1401   - // 修正午饭之后路牌班次的发车时间
1402   - oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
1403   - oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
1404   - }
1405   - }
1406   - }
1407   - }
1408   -
1409   - },
1410   -
1411   - /**
1412   - * 补每个路牌的其他班次(进出场,例保班次)。
1413   - */
1414   - fnCalcuOtherBc: function() {
1415   - var i;
1416   - var _lpObj;
1417   - var _minBcIndex;
1418   - var _maxBcIndex;
1419   - var _minBc;
1420   - var _maxBc;
1421   - var _otherbc = [];
1422   -
1423   - for (i = 0; i < _internalLpArray.length; i++) {
1424   - _lpObj = _internalLpArray[i];
1425   - _minBcIndex = _lpObj.getMinBcObjPosition();
1426   - _maxBcIndex = _lpObj.getMaxBcObjPosition();
1427   - _minBc = _lpObj.getBc(_minBcIndex[0], _minBcIndex[1]);
1428   - _maxBc = _lpObj.getBc(_maxBcIndex[0], _maxBcIndex[1]);
1429   -
1430   - _otherbc = [];
1431   - //_otherbc.push(_factory.createBcObj(
1432   - // _lpObj, "bd", true, 1,
1433   - // _minBc.getFcTimeObj(),
1434   - // _paramObj
1435   - //));
1436   - _otherbc.push(_factory.createBcObj(
1437   - _lpObj, "out", true, 1,
1438   - _minBc.getFcTimeObj(),
1439   - _paramObj
1440   - ));
1441   -
1442   - _maxBc.setArrTimeObj(_paramObj.addMinute(_maxBc.getFcTimeObj(), _maxBc.getBcTime()));
1443   - _maxBc.setStopTime(0);
1444   - _otherbc.push(_factory.createBcObj(
1445   - _lpObj, "in", true, 1,
1446   - _maxBc.getArrTimeObj(),
1447   - _paramObj
1448   - ));
1449   - //_otherbc.push(_factory.createBcObj(
1450   - // _lpObj, "lc", true, 1,
1451   - // _maxBc.getArrTimeObj(),
1452   - // _paramObj
1453   - //));
1454   -
1455   - _lpObj.addOtherBcArray(_otherbc);
1456   - }
1457   -
1458   - },
1459   -
1460   - /**
1461   - * 祛除上标线有删除标记的班次。
1462   - */
1463   - fnRemoveDelFlagBc: function() {
1464   - var oLp = _internalLpArray[0];
1465   - var aMinBcIndex = oLp.getMinBcObjPosition();
1466   - oLp.removeBc(aMinBcIndex[0], aMinBcIndex[1]);
1467   -
1468   - var aMaxBcIndex = oLp.getMaxBcObjPosition();
1469   - if (oLp.getBc(aMaxBcIndex[0], aMaxBcIndex[1]).fnIsDelFlag()) {
1470   - oLp.removeBc(aMaxBcIndex[0], aMaxBcIndex[1]);
1471   - }
1472   - },
1473   -
1474   - /**
1475   - * 调整班次纵向间隔(发车时间调整)。
1476   - * 1、只调整分班班次的发车时间
1477   - * 2、调整每两个连班之间的分班班次组
1478   - * 3、如果不是连续的班次才调整
1479   - */
1480   - fnAdjust_vertical_bc_interval: function() {
1481   - var i;
1482   - var j;
1483   - var iBIndex = 0;
1484   - var oLbGroup = {};
1485   - var oLp;
1486   - for (i = 0; i < _qCount; i++) {
1487   - while (iBIndex <= 1) {
1488   - oLbGroup[i + "_" + iBIndex] = [];
1489   - for (j = 0; j < _internalLpArray.length; j++) {
1490   - oLp = _internalLpArray[j];
1491   - if (oLp.isBxLb()) {
1492   - if (oLp.getBc(i, iBIndex)) {
1493   - oLbGroup[i + "_" + iBIndex].push(j);
1494   - }
1495   - }
1496   - }
1497   - if (oLbGroup[i + "_" + iBIndex].length == 1) {
1498   - oLbGroup[i + "_" + iBIndex] = [];
1499   - }
1500   -
1501   - iBIndex ++;
1502   - }
1503   - iBIndex = 0;
1504   - }
1505   -
1506   - //console.log(oLbGroup);
1507   -
1508   - var sKey;
1509   - var iQindex;
1510   - var iBindex;
1511   - var aBcLb = [];
1512   -
1513   - var oLbGroup_m = {};
1514   - var aLbGroup = [];
1515   -
1516   -
1517   - // 计算需要调整的连班区间
1518   - for (sKey in oLbGroup) {
1519   - iQindex = sKey.split('_')[0];
1520   - iBindex = sKey.split('_')[1];
1521   - oLbGroup_m[sKey] = [];
1522   - for (i = 0; i < oLbGroup[sKey].length - 1; i++) {
1523   - aBcLb = [];
1524   - for (j = oLbGroup[sKey][i] + 1; j <= oLbGroup[sKey][i + 1] - 1; j++) {
1525   - oLp = _internalLpArray[j];
1526   - if (oLp.getBc(iQindex, iBindex)) {
1527   - aBcLb.push(j);
1528   - }
1529   - }
1530   - if (aBcLb.length != 0 && aBcLb.length < (oLbGroup[sKey][i + 1] - oLbGroup[sKey][i] - 1)) {
1531   - aLbGroup = [];
1532   - aLbGroup.push(oLbGroup[sKey][i]);
1533   - aLbGroup.push(oLbGroup[sKey][i + 1]);
1534   - aLbGroup.push(aBcLb);
1535   - oLbGroup_m[sKey].push(aLbGroup);
1536   - }
1537   - }
1538   - }
1539   -
1540   - console.log(oLbGroup_m);
1541   -
1542   - var iStartLpIndex;
1543   - var iEndLpIndex;
1544   - var iDCount;
1545   - var iDiffTime;
1546   -
1547   - var iC1;
1548   - var iC2;
1549   - var oKssj;
1550   -
1551   - for (sKey in oLbGroup_m) {
1552   - iQindex = sKey.split('_')[0];
1553   - iBindex = sKey.split('_')[1];
1554   -
1555   - for (i = 0; i < oLbGroup_m[sKey].length; i++) {
1556   - aLbGroup = oLbGroup_m[sKey][i];
1557   -
1558   - iStartLpIndex = aLbGroup[0];
1559   - iEndLpIndex = aLbGroup[1];
1560   - iDCount = aLbGroup[2].length + 1;
1561   -
1562   - iDiffTime = _internalLpArray[iEndLpIndex].getBc(iQindex, iBindex).getFcTimeObj().diff(
1563   - _internalLpArray[iStartLpIndex].getBc(iQindex, iBindex).getFcTimeObj(), 'm');
1564   -
1565   - iC1 = Math.floor(iDiffTime / iDCount);
1566   - iC2 = iDiffTime % iDCount;
1567   - oKssj = _internalLpArray[iStartLpIndex].getBc(iQindex, iBindex).getFcTimeObj();
1568   -
1569   - for (j = 1; j <= iDCount - iC2; j++) {
1570   - if (j - 1 < aLbGroup[2].length) {
1571   - oKssj = _paramObj.addMinute(oKssj, iC1);
1572   - _internalLpArray[aLbGroup[2][j - 1]].getBc(
1573   - iQindex, iBindex).setFcTimeObj(oKssj);
1574   - }
1575   - }
1576   -
1577   - for (j = 1; j < iC2; j++) {
1578   - oKssj = _paramObj.addMinute(oKssj, iC1 + 1);
1579   - _internalLpArray[aLbGroup[2][iDCount - iC2 + j - 1]].getBc(
1580   - iQindex, iBindex).setFcTimeObj(oKssj);
1581   - }
1582   -
1583   - }
1584   - }
1585   -
1586   - },
1587   -
1588   - //------------- 其他方法 -------------//
1589   - /**
1590   - * 内部数据转化成显示用的班次数组。
1591   - */
1592   - fnToGanttBcArray: function() {
1593   - var aAllBc = [];
1594   - var aLpBc = [];
1595   - var oLp;
1596   - var i;
1597   - var j;
1598   -
1599   - for (i = 0; i < _internalLpArray.length; i++) {
1600   - oLp = _internalLpArray[i];
1601   - aLpBc = [];
1602   - aLpBc = aLpBc.concat(oLp.getOtherBcArray(), oLp.getBcArray());
1603   - // 按照发车时间排序
1604   - aLpBc.sort(function(o1, o2) {
1605   - if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
1606   - return -1;
1607   - } else {
1608   - return 1;
1609   - }
1610   - });
1611   -
1612   - // 重新赋值fcno
1613   - for (j = 0; j < aLpBc.length; j++) {
1614   - aLpBc[j].fnSetFcno(j + 1);
1615   - }
1616   -
1617   - aAllBc = aAllBc.concat(aLpBc);
1618   - }
1619   -
1620   - var aGanttBc = [];
1621   - for (i = 0; i < aAllBc.length; i++) {
1622   - aGanttBc.push(aAllBc[i].toGanttBcObj());
1623   - }
1624   -
1625   - return aGanttBc;
1626   - }
1627   -
1628   - };
1629   -
  1 +/**
  2 + * 内部行车计划对象。
  3 + * @constructor
  4 + */
  5 +var InternalScheduleObj = function(paramObj, lpArray, factory) {
  6 + // 参数对象
  7 + var _paramObj = paramObj;
  8 + // 外部的路牌数组
  9 + var _lpArray = lpArray;
  10 + // 工厂对象
  11 + var _factory = factory;
  12 +
  13 + //------------------ 初始化方法1,以及计算关联的内部变量 -----------------//
  14 + var _qIsUp; // 每一圈是上行开始还是下行开始
  15 + var _qCount = 0; // 总的圈数
  16 + var _internalLpArray = []; // 内部对象数组
  17 + var _aBxDesc = [ // 各种班型描述(班型名称,平均工时,平均需要的班次数,平均工时)
  18 + {'sType':'六工一休', 'fHoursV':6.66, 'fBcCount': 0, 'fAverTime': 0},
  19 + {'sType':'五工一休', 'fHoursV':6.85, 'fBcCount': 0, 'fAverTime': 0},
  20 + {'sType':'四工一休', 'fHoursV':7.14, 'fBcCount': 0, 'fAverTime': 0},
  21 + {'sType':'三工一休', 'fHoursV':7.61, 'fBcCount': 0, 'fAverTime': 0},
  22 + {'sType':'二工一休', 'fHoursV':8.57, 'fBcCount': 0, 'fAverTime': 0},
  23 + {'sType':'一工一休', 'fHoursV':11.42, 'fBcCount': 0, 'fAverTime': 0},
  24 + {'sType':'五工二休', 'fHoursV':7.99, 'fBcCount': 0, 'fAverTime': 0},
  25 + {'sType':'无工休', 'fHoursV':5.43, 'fBcCount': 0, 'fAverTime': 0}
  26 + ];
  27 +
  28 + var _fnInitFun1 = function() { // 初始化方法1
  29 + console.log("//---------------- 行车计划,初始化方法1 start ----------------//");
  30 +
  31 + //----------------------- 1、确定上标线的方向,圈的方向 -------------------//
  32 +
  33 + // 确定_qIsUp,哪个方向的首班车晚就用哪个
  34 + _qIsUp = _paramObj.getUpFirstDTimeObj().isBefore(
  35 + _paramObj.getDownFirstDTimeObj()) ? false : true;
  36 + // 上标线开始时间,就是方向的首班车时间
  37 + var st = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
  38 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  39 + var et;
  40 + var et_IsUp;
  41 + if (_paramObj.getUpLastDtimeObj().isBefore(
  42 + _paramObj.getDownLastDTimeObj())) {
  43 + et = _paramObj.getDownLastDTimeObj();
  44 + et_IsUp = false;
  45 + } else {
  46 + et = _paramObj.getUpLastDtimeObj();
  47 + et_IsUp = true;
  48 + }
  49 +
  50 + //------------------------ 2、计算总共有多少圈 ------------------------//
  51 +
  52 + // 以开始时间,结束时间,构造上标线用连班班次发车时间
  53 + var bcFcsjArrays = []; // 班次发车时间对象数组
  54 + var bcArsjArrays = []; // 班次到达时间对象数组
  55 + var isUp = _qIsUp; // 方向
  56 + var bcCount = 1; // 班次数
  57 +
  58 + var _kssj = st; // 开始时间
  59 + var _bcsj = paramObj.calcuTravelTime(_kssj, isUp); // 班次历时
  60 + var _arrsj = paramObj.addMinute(_kssj, _bcsj); // 到达时间
  61 + var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj); // 停站时间
  62 +
  63 + do {
  64 + bcFcsjArrays.push(_kssj);
  65 + bcArsjArrays.push(_arrsj);
  66 +
  67 + _kssj = paramObj.addMinute(_kssj, _bcsj + _stoptime);
  68 + _bcsj = paramObj.calcuTravelTime(_kssj, isUp);
  69 + _arrsj = paramObj.addMinute(_kssj, _bcsj);
  70 + _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
  71 +
  72 + bcCount ++;
  73 + isUp = !isUp;
  74 + } while(_kssj.isBefore(et));
  75 + bcCount--; // 因为先做do,所以总的班次要减1
  76 + if (bcCount > 0 && bcArsjArrays[bcCount - 1].isAfter(et)) {
  77 + // 如果最后一个班次的到达时间超过结束时间,也要去除
  78 + bcFcsjArrays.splice(bcCount - 1, 1);
  79 + bcArsjArrays.splice(bcCount - 1, 1);
  80 + bcCount--;
  81 + }
  82 + var _qCount_p1 = Math.floor(bcCount / 2); // 2个班次一圈
  83 + var _qCount_p2 = bcCount % 2; // 余下的1个班次也算一圈
  84 +
  85 + // 利用连班数组计算圈数
  86 + _qCount = 1; // 前面加1圈,补中标线的班次
  87 + _qCount += _qCount_p1;
  88 + _qCount += _qCount_p2;
  89 +
  90 + // 计算最后是不是还要补一圈
  91 + if (_qCount > 1) { // 总的圈数就1圈,没必要加了(其实是不可能的,除非参数里问题)
  92 + if (_qCount_p2 == 0) { // 没有余下班次,整数圈数
  93 + // 最后一个班次的方向一定和开始的方向相反,如:上-下,上-下,上-下,一共三圈,最后一个班次为下行
  94 + // 判定最后一个班次的方向和上标线判定结束时间的班次方向是否一致
  95 + if (!_qIsUp == et_IsUp) {
  96 + // 一致不用加圈数
  97 + } else {
  98 + // 不一致需要加圈补最后一个结束时间班次
  99 + _qCount ++;
  100 + }
  101 + } else {
  102 + // 有余下的圈数,最后要不补的班次不管上行,下行都在这一圈里
  103 + // 不需要在补圈数了
  104 + }
  105 + }
  106 +
  107 + //------------------------ 3、根据路牌数,圈数创建路牌对象 ----------------------//
  108 +
  109 + // 创建内部的路牌数组,并把之前的连班路牌添加进上标线路牌中
  110 + var i;
  111 + for (i = 0; i < _lpArray.length; i++) {
  112 + _internalLpArray.push(new InternalLpObj(_lpArray[i], _qCount, _qIsUp));
  113 + }
  114 + // 初始化上标线,从第1圈开始
  115 + _internalLpArray[0].initDataFromTimeToTime(bcFcsjArrays[0], et, _qIsUp, 1, _paramObj, _factory);
  116 +
  117 + // 以上标线为基础,计算各种班型工时对应的圈数、班次数
  118 + var aBcArray = _internalLpArray[0].getBcArray();
  119 + if (aBcArray.length % 2 != 0) { // 不能整除2,去除一个班次计算
  120 + aBcArray.splice(aBcArray.length - 1, 1);
  121 + }
  122 + var sum = 0;
  123 + // 加吃饭时间
  124 + sum += _paramObj.fnGetLunchTime();
  125 + sum += _paramObj.fnGetDinnerTime();
  126 + // 加进出场时间
  127 + sum += _qIsUp ? _paramObj.getUpOutTime() : _paramObj.getDownOutTime();
  128 + sum += _qIsUp ? _paramObj.getDownInTime() : _paramObj.getUpInTime();
  129 + // 例保时间
  130 + //sum += _paramObj.getLbTime() * 2;
  131 + for (i = 0; i < aBcArray.length; i++) {
  132 + sum += aBcArray[i].getBcTime() + aBcArray[i].getStopTime();
  133 + }
  134 + for (i = 0; i < _aBxDesc.length; i++) {
  135 + _aBxDesc[i].fAverTime = sum / (aBcArray.length / 2);
  136 + _aBxDesc[i].fBcCount = ((_aBxDesc[i].fHoursV * 60) / _aBxDesc[i].fAverTime) * 2;
  137 + }
  138 +
  139 + // 在第一个班次之前再添加一个模拟班次,用于中标线的作用
  140 + // 那一圈必定是低谷,而且圈索引0,班次索引1,暂时标记,最后删除
  141 + var iFirstStopTime =
  142 + _paramObj.fnCalcuFixedStopNumber(
  143 + _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -10),
  144 + _qIsUp
  145 + );
  146 + var iXXTime = _qIsUp ? _paramObj.getDownTroughTime() : _paramObj.getUpTroughTime();
  147 + var oFlagBc = _factory.createBcObj( // 标记班次
  148 + _internalLpArray[0],
  149 + "normal",
  150 + !_qIsUp,
  151 + 1,
  152 + _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -(iFirstStopTime + iXXTime)),
  153 + _paramObj
  154 + );
  155 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  156 +
  157 + _internalLpArray[0].setBc(0, 1, oFlagBc);
  158 +
  159 + // 在最后一圈也补上一个或者2个模拟班次,暂时标记,最后需要删除
  160 + var aMaxBcIndex = _internalLpArray[0].getMaxBcObjPosition();
  161 + if (aMaxBcIndex[0] == _qCount - 1) { // 可能加半圈
  162 + oFlagBc = _factory.createBcObj( // 标记班次
  163 + _internalLpArray[0],
  164 + "normal",
  165 + !_qIsUp,
  166 + 1,
  167 + _paramObj.addMinute(
  168 + _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
  169 + _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
  170 + _paramObj
  171 + );
  172 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  173 + _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
  174 +
  175 + } else { // 加完整的一圈
  176 + oFlagBc = _factory.createBcObj( // 标记班次
  177 + _internalLpArray[0],
  178 + "normal",
  179 + _qIsUp,
  180 + 1,
  181 + _paramObj.addMinute(
  182 + _internalLpArray[0].getBc(_qCount - 2, 1).getArrTimeObj(),
  183 + _internalLpArray[0].getBc(_qCount - 2, 1).getStopTime()),
  184 + _paramObj
  185 + );
  186 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  187 + _internalLpArray[0].setBc(_qCount - 1, 0, oFlagBc);
  188 +
  189 + oFlagBc = _factory.createBcObj( // 标记班次
  190 + _internalLpArray[0],
  191 + "normal",
  192 + !_qIsUp,
  193 + 1,
  194 + _paramObj.addMinute(
  195 + _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
  196 + _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
  197 + _paramObj
  198 + );
  199 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  200 + _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
  201 +
  202 + }
  203 +
  204 + console.log("上行首班车时间:" + _paramObj.getUpFirstDTimeObj().format("HH:mm") +
  205 + "上行末班车时间:" + _paramObj.getUpLastDtimeObj().format("HH:mm"));
  206 + console.log("下行首班车时间:" + _paramObj.getDownFirstDTimeObj().format("HH:mm") +
  207 + "下行末班车时间:" + _paramObj.getDownLastDTimeObj().format("HH:mm"));
  208 + console.log("总共计算的圈数:" + _qCount);
  209 + console.log("圈的方向isUP:" + _qIsUp);
  210 + console.log("班型描述(以下):");
  211 + console.log(_aBxDesc);
  212 + console.log("所有路牌间隔描述(以下):");
  213 + for (i = 0; i < _internalLpArray.length; i++) {
  214 + console.log(_internalLpArray[i]._$_aVerticalIntervalTime);
  215 + }
  216 + console.log("//---------------- 行车计划,初始化方法1 end ----------------//");
  217 +
  218 + };
  219 +
  220 + //------------------ 初始化方法2,以及计算关联的内部变量 ----------------//
  221 + var _approximate_zgfQIndex; // 预估早高峰车辆从第几圈开始全部发出
  222 + var _approximate_zgfBIndex; // 预估早高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
  223 + var _approximate_wgfQIndex; // 预估晚高峰车辆从第几圈开始全部发出
  224 + var _approximate_wgfBIndex; // 预估晚高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
  225 +
  226 + var _fnInitFun2 = function() { // 初始化方法2
  227 + console.log("//---------------- 行车计划,初始化方法2 start ----------------//");
  228 +
  229 + //------------------------ 1、计算车辆总数 ------------------------//
  230 + // 是用高峰上行周转时间除以高峰平均间隔得到的
  231 + // 这样算还算合理,车辆不多不少,待以后有新的算法再修正
  232 + var iClCount = _paramObj.calcuClzx();
  233 +
  234 + //------------------------ 2、计算所有路牌的发车在各个圈中的间隔 --------------------//
  235 + var i;
  236 + var j;
  237 + var iBindex = 1;
  238 + var iZzsj;
  239 + var oLp;
  240 + var iC1;
  241 + var iC2;
  242 +
  243 + for (i = 0; i < _qCount - 1; i++) {
  244 + while (iBindex <= 1) {
  245 + // 每圈每个方向的周转时间不一致,以上标线为主
  246 + oLp = _internalLpArray[0];
  247 + iZzsj = oLp.getBc(i + 1, iBindex).getFcTimeObj().diff(
  248 + oLp.getBc(i, iBindex).getFcTimeObj(), "m"
  249 + );
  250 +
  251 + iC1 = Math.floor(iZzsj / iClCount);
  252 + iC2 = iZzsj % iClCount;
  253 +
  254 + for (j = 0; j < iClCount - iC2; j++) {
  255 + oLp = _internalLpArray[j];
  256 + oLp.fnSetVerticalIntervalTime(i, iBindex, iC1);
  257 + }
  258 +
  259 + for (j = 0; j < iC2; j++) {
  260 + oLp = _internalLpArray[iClCount - iC2 + j];
  261 + oLp.fnSetVerticalIntervalTime(i, iBindex, iC1 + 1);
  262 + }
  263 +
  264 + iBindex ++;
  265 +
  266 + }
  267 + iBindex = 0;
  268 + }
  269 + // 最后一圈没有下一圈的参照,周转时间没发获取,由于都是低谷,所以使用倒数第二圈的间隔最为最后一圈的间隔
  270 + for (i = 0; i < _internalLpArray.length; i++) {
  271 + oLp = _internalLpArray[i];
  272 + oLp.fnSetVerticalIntervalTime(_qCount - 1, 0, oLp.fnGetVerticalIntervalTime(_qCount - 2, 0));
  273 + oLp.fnSetVerticalIntervalTime(_qCount - 1, 1, oLp.fnGetVerticalIntervalTime(_qCount - 2, 1));
  274 + }
  275 +
  276 + //------------------------ 3、预估早高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
  277 +
  278 + // 以上标线为标准,查找离早高峰开始时间最近的班次作为早高峰开始班次
  279 + // 以这个班次为早高峰起点,全部出车策略
  280 + var qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
  281 + _paramObj.getMPeakStartTimeObj(), true, true);
  282 + var qIndex = qbcIndexArray[0]; // 第几圈
  283 + var bIndex = qbcIndexArray[1]; // 第几个班次
  284 +
  285 + for (i = 1; i < _internalLpArray.length; i++) {
  286 + _fnGenerateBcAndSetBc(i, qIndex, bIndex);
  287 + }
  288 +
  289 + _approximate_zgfQIndex = qIndex;
  290 + _approximate_zgfBIndex = bIndex;
  291 +
  292 + //------------------------ 4、预估晚高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
  293 +
  294 + // 以上标线为标准,查找离晚高峰开始时间最近的班次作为晚高峰开始班次
  295 + // 以这个班次为早高峰起点,全部出车策略
  296 + qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
  297 + _paramObj.getEPeakStartTimeObj(), true, true);
  298 + qIndex = qbcIndexArray[0]; // 第几圈
  299 + bIndex = qbcIndexArray[1]; // 第几个班次
  300 +
  301 + for (i = 1; i < _internalLpArray.length; i++) {
  302 + _fnGenerateBcAndSetBc(i, qIndex, bIndex);
  303 + }
  304 +
  305 + _approximate_wgfQIndex = qIndex;
  306 + _approximate_wgfBIndex = bIndex;
  307 +
  308 + console.log("早高峰周转时间(固定最大停战时间):" + _paramObj.calcuPeakZzsj() + "分钟");
  309 + console.log("早高峰发车时间范围:" + _paramObj.getMPeakMinFcjx() + "分钟 --- " + _paramObj.getMPeakMaxFcjx() + "分钟");
  310 + console.log("预估早高峰第" + _approximate_zgfQIndex + "(index)圈,第" + _approximate_zgfBIndex + "(index)班次车辆全部发出");
  311 + console.log("预估晚高峰第" + _approximate_wgfQIndex + "(index)圈,第" + _approximate_wgfBIndex + "(index)班次车辆全部发出");
  312 + console.log("//---------------- 行车计划,初始化方法2 end ----------------//");
  313 + };
  314 +
  315 + //----------------------- 初始化方法3,计算连班分班的路牌分布 ----------------//
  316 + var _iBx_lb_lpcount; // 连班路牌数
  317 + var _iBx_5_2_fb_lpcount; // 5休2分班路牌数
  318 + var _iBx_other_fb_lpcount; // 其他分班路牌数
  319 +
  320 + var _fnInitFun3 = function() { // 初始化方法3
  321 + console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
  322 +
  323 + //--------------------- 1、计算分班连班班型车辆分布数 --------------------//
  324 + // 总共车辆数(高峰最大车辆数)
  325 + var iCls = _paramObj.calcuClzx();
  326 + // 低谷最少配车(连班车数量)
  327 + var iDgminpc = Math.round(_paramObj.calcuTroughZzsj() / _paramObj.getTroughMaxFcjx());
  328 + // 加班车路牌数(做5休2的路牌数)
  329 + var i_5_2_lpes = _paramObj.getJBLpes();
  330 +
  331 + // 做些简单的验证
  332 + if (iCls < iDgminpc) {
  333 + alert("总配车数小于低谷最小配车");
  334 + throw "总配车数小于低谷最小配车";
  335 + }
  336 + if (iDgminpc < 2) {
  337 + alert("连班路牌小于2,办不到啊");
  338 + throw "连班路牌小于2,办不到啊";
  339 + }
  340 + if (iCls - iDgminpc < i_5_2_lpes) {
  341 + alert("总分班路牌数小于加班路牌数");
  342 + throw "总分班路牌数小于加班路牌数";
  343 + }
  344 +
  345 + _iBx_lb_lpcount = iDgminpc;
  346 + _iBx_5_2_fb_lpcount = i_5_2_lpes;
  347 + _iBx_other_fb_lpcount = iCls - iDgminpc - i_5_2_lpes;
  348 +
  349 + //------------------------ 2、利用间隔法计算连班路牌分布 --------------------//
  350 + var i;
  351 + var j;
  352 + var iC1 = Math.floor(_internalLpArray.length / _iBx_lb_lpcount);
  353 + var iC2 = _internalLpArray.length % _iBx_lb_lpcount;
  354 + var iLpIndex;
  355 +
  356 + for (i = 0; i < _iBx_lb_lpcount - iC2; i++) {
  357 + iLpIndex = i * iC1;
  358 + _internalLpArray[iLpIndex].setBxLb(true);
  359 + _internalLpArray[iLpIndex].setBxDesc("连班");
  360 + }
  361 + for (j = 0; j < iC2; j++) {
  362 + iLpIndex = i * iC1 + j * (iC1 + 1);
  363 + _internalLpArray[iLpIndex].setBxLb(true);
  364 + _internalLpArray[iLpIndex].setBxDesc("连班");
  365 + }
  366 +
  367 + //------------------------ 3、利用间隔法计算分班班型路牌分布 --------------------//
  368 + // 获取分班路牌索引
  369 + var aNotLbIndexes = [];
  370 + for (i = 0; i < _internalLpArray.length; i++) {
  371 + if (!_internalLpArray[i].isBxLb()) {
  372 + aNotLbIndexes.push(i);
  373 + }
  374 + }
  375 + // 先5休2分班
  376 + iC1 = Math.floor(aNotLbIndexes.length / _iBx_5_2_fb_lpcount);
  377 + iC2 = aNotLbIndexes.length % _iBx_5_2_fb_lpcount;
  378 +
  379 + for (i = 0; i < _iBx_5_2_fb_lpcount - iC2; i++) {
  380 + iLpIndex = aNotLbIndexes[i * iC1];
  381 + _internalLpArray[iLpIndex].setBxLb(false);
  382 + _internalLpArray[iLpIndex].setBxFb(true);
  383 + _internalLpArray[iLpIndex].setBxFb5_2(true);
  384 + _internalLpArray[iLpIndex].setBxDesc("5休2分班");
  385 + }
  386 + for (i = 0; i < iC2; i++) {
  387 + iLpIndex = aNotLbIndexes[_iBx_lb_lpcount - iC2 + i * (iC1 + 1)];
  388 + _internalLpArray[iLpIndex].setBxLb(false);
  389 + _internalLpArray[iLpIndex].setBxFb(true);
  390 + _internalLpArray[iLpIndex].setBxFb5_2(true);
  391 + _internalLpArray[iLpIndex].setBxDesc("5休2分班");
  392 + }
  393 + // 其他分班
  394 + for (i = 0; i < aNotLbIndexes.length; i++) {
  395 + iLpIndex = aNotLbIndexes[i];
  396 + if (!_internalLpArray[iLpIndex].isBxFb5_2()) {
  397 + _internalLpArray[iLpIndex].setBxLb(false);
  398 + _internalLpArray[iLpIndex].setBxFb(true);
  399 + _internalLpArray[iLpIndex].setBxFb5_2(false);
  400 + _internalLpArray[iLpIndex].setBxDesc("其他分班");
  401 + }
  402 + }
  403 +
  404 +
  405 + console.log("连班路牌数:" + _iBx_lb_lpcount);
  406 + console.log("5休2分班路牌数:" + _iBx_5_2_fb_lpcount);
  407 + console.log("其他分班路牌数:" + _iBx_other_fb_lpcount);
  408 + var aLbIndexes = [];
  409 + for (i = 0; i < _internalLpArray.length; i++) {
  410 + if (_internalLpArray[i].isBxLb()) {
  411 + aLbIndexes.push(i);
  412 + }
  413 + }
  414 + console.log("连班路牌indexes=" + aLbIndexes);
  415 + var a_5_2_fbIndexes = [];
  416 + for (i = 0; i < _internalLpArray.length; i++) {
  417 + if (_internalLpArray[i].isBxFb() && _internalLpArray[i].isBxFb5_2()) {
  418 + a_5_2_fbIndexes.push(i);
  419 + }
  420 + }
  421 + console.log("5休2分班路牌indexes=" + a_5_2_fbIndexes);
  422 + var a_other_fbIndexes = [];
  423 + for (i = 0; i < _internalLpArray.length; i++) {
  424 + if (_internalLpArray[i].isBxFb() && !_internalLpArray[i].isBxFb5_2()) {
  425 + a_other_fbIndexes.push(i);
  426 + }
  427 + }
  428 + console.log("其他分班路牌indexes=" + a_other_fbIndexes);
  429 +
  430 + console.log("//---------------- 行车计划,初始化方法3 end ----------------//");
  431 + };
  432 +
  433 + //----------------------- 初始化方法4,计算中标线位置 -------------------------//
  434 + var _iZbx_lpIndex; // 中标线对应第几个路牌
  435 +
  436 + var _fnInitFun4 = function() { // 初始化方法4
  437 + console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
  438 +
  439 + //---------------------------- 1、模拟一个中标线,使用临时路牌 ----------------------//
  440 + // 构造中标线
  441 + // 中标线开始时间,就是方向的首班车时间
  442 + var oSt = !_qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
  443 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  444 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  445 + var oEt;
  446 + if (_paramObj.getUpLastDtimeObj().isBefore(
  447 + _paramObj.getDownLastDTimeObj())) {
  448 + oEt = _paramObj.getDownLastDTimeObj();
  449 + } else {
  450 + oEt = _paramObj.getUpLastDtimeObj();
  451 + }
  452 +
  453 + var oTempLp = new InternalLpObj({lpNo: -999, lpName: "-999"}, _qCount, _qIsUp);
  454 + oTempLp.initDataFromTimeToTime(
  455 + oSt,
  456 + oEt,
  457 + !_qIsUp,
  458 + 0,
  459 + _paramObj,
  460 + _factory
  461 + );
  462 +
  463 + //------------------------ 2、找出中标线的早高峰班次,计算应该插在当前路牌数组的那个位置 ----------------//
  464 + // 找出中标线对应的早高峰的班次对象
  465 + var oZb_gf_bc = oTempLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
  466 +
  467 + // 把所有连班路牌高峰班次重新构造成一个一个的圈数组,计算对应中标线最近的是第几个路牌
  468 + // 中标线和上标线一样在连班路牌上
  469 + var aTempq = [];
  470 + var oTempq;
  471 + var oTempb;
  472 + var i;
  473 + var oLp;
  474 +
  475 + var aLbIndexes = []; // 连班的路牌索引
  476 + for (i = 0; i < _internalLpArray.length; i++) {
  477 + if (_internalLpArray[i].isBxLb()) {
  478 + aLbIndexes.push(i);
  479 + }
  480 + }
  481 +
  482 + for (i = 0; i < aLbIndexes.length; i++) {
  483 + oLp = _internalLpArray[aLbIndexes[i]];
  484 +
  485 + oTempb = oLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
  486 + if (oTempb.isUp() == _qIsUp) {
  487 + oTempq = new InternalGroupObj(oLp, _qIsUp, oTempb, undefined);
  488 + } else {
  489 + oTempq = new InternalGroupObj(oLp, _qIsUp, undefined, oTempb);
  490 + }
  491 + aTempq.push(oTempq);
  492 +
  493 + }
  494 +
  495 + var aTtindex = oTempLp.getgetQBcIndexWithFcTimeFromGroupArray(
  496 + oZb_gf_bc.getFcTimeObj(),
  497 + aTempq,
  498 + true,
  499 + true
  500 + );
  501 +
  502 + _iZbx_lpIndex = aLbIndexes[aTtindex[0]]; // 中标线放在第几个路牌
  503 + oTempLp.setLp(_lpArray[_iZbx_lpIndex]); // 设置原始路牌对象
  504 + oTempLp._$_aVerticalIntervalTime = _internalLpArray[_iZbx_lpIndex]._$_aVerticalIntervalTime; // 设置纵向最小发车间隔
  505 + oTempLp.setBxLb(_internalLpArray[_iZbx_lpIndex].isBxLb());
  506 + oTempLp.setBxFb(_internalLpArray[_iZbx_lpIndex].isBxFb());
  507 + oTempLp.setBxFb5_2(_internalLpArray[_iZbx_lpIndex].isBxFb5_2());
  508 +
  509 + // 修正除了第一个班次外,其余其他班次
  510 + var iBcindex = 0;
  511 + for (i = 1; i < _qCount; i++) {
  512 + while (iBcindex <= 1) {
  513 + if (oTempLp.getBc(i, iBcindex)) { // 替换存在的班次
  514 + oTempLp.setBc(i, iBcindex, _fnGenerateBc(_iZbx_lpIndex, i, iBcindex));
  515 + }
  516 + iBcindex ++;
  517 + }
  518 + iBcindex = 0;
  519 + }
  520 +
  521 + _internalLpArray[_iZbx_lpIndex] = oTempLp;
  522 +
  523 + console.log("中标线对应第" + (_iZbx_lpIndex + 1) + "个路牌");
  524 +
  525 + console.log("//---------------- 行车计划,初始化方法4 end ----------------//");
  526 + };
  527 +
  528 + //-------------------- 重要的内部方法 -----------------------//
  529 + /**
  530 + * 核心方法,利用路牌间隔纵向生成班次。
  531 + * @param iLpindex 路牌索引
  532 + * @param iQindex 圈索引
  533 + * @param iBcindex 班次索引
  534 + * @returns object InternalBcObj,失败 false
  535 + */
  536 + var _fnGenerateBc = function(iLpindex, iQindex, iBcindex) {
  537 + // 以上标线为起始点,使用路牌在不同圈,班次索引的发车间隔,计算班次
  538 + // 注意,发车间隔是指下一个班次应该距离当前班次间隔,是从下往上的
  539 +
  540 + // 1、参数验证
  541 + if (iLpindex == 0) { // 上标线的班次不需要生成
  542 + return false;
  543 + }
  544 +
  545 + // 2、计算间隔
  546 + var i;
  547 + var oLp;
  548 + var iTime = 0;
  549 + for (i = 0; i < iLpindex; i++) {
  550 + oLp = _internalLpArray[i];
  551 + iTime += oLp.fnGetVerticalIntervalTime(iQindex, iBcindex);
  552 + }
  553 +
  554 + // 3、生成班次
  555 + var _oKsbc = _internalLpArray[0].getBc(iQindex, iBcindex);
  556 + if (!_oKsbc) {
  557 + return false;
  558 + }
  559 + var _oKssj = _paramObj.addMinute(_oKsbc.getFcTimeObj(), iTime);
  560 + var _oBc = _factory.createBcObj(
  561 + _internalLpArray[iLpindex],
  562 + "normal", _oKsbc.isUp(),
  563 + 1, _oKssj, _paramObj);
  564 +
  565 + return _oBc;
  566 +
  567 + };
  568 +
  569 + /**
  570 + * 核心方法,在指定位置生成班次并添加到路牌指定位置中。
  571 + * @param lpIndex 第几个路牌
  572 + * @param qIndex 第几圈
  573 + * @param bcIndex 第几个班次
  574 + */
  575 + var _fnGenerateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
  576 + var _bcObj = _fnGenerateBc(lpIndex, qIndex, bcIndex);
  577 + if (_bcObj) {
  578 + _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
  579 + }
  580 + };
  581 +
  582 +
  583 + /**
  584 + * 在指定位置生成班次(内部重要方法)。
  585 + * @param lpIndex 第几个路牌
  586 + * @param qIndex 第几圈
  587 + * @param bcIndex 第几个班次
  588 + * @returns InternalBcObj
  589 + */
  590 + var _generateBc = function(lpIndex, qIndex, bcIndex) {
  591 + // 在初始化布局后使用,否则没有参照班次加不了
  592 + // 初始化布局后,相当于把时刻表比作一个围棋棋盘,行为路牌数,列为圈数
  593 + // 上标线,中标线,早晚高峰已经布局在棋盘上,其余的空格可以创建班次
  594 +
  595 + // 这个生成班次是以上一班次时间,以发车间隔为基础添加的,纵向加
  596 + // 和生成标线时那种一直往后加班次时不一样,那种是以前一个班次为基础,横向加
  597 +
  598 + // 1、生成的班次以同一圈同一个方向里离它最早的班次的发车时间为基础
  599 + // 2、以每个路牌的纵向最小发车间隔时间为计算发车间隔
  600 + // 3、如果班次发车时间越界不管,有其余方法排除这种情况
  601 +
  602 + // 1、查找同圈同方向里最近的班次,找不到报错(因为有标线存在是不可能找不到的)
  603 + var _i;
  604 + var _bcObj;
  605 + for (_i = lpIndex - 1; _i >= 0; _i--) {
  606 + _bcObj = _internalLpArray[_i].getBc(qIndex, bcIndex);
  607 + if (_bcObj) {
  608 + break;
  609 + }
  610 + }
  611 + if (!_bcObj) {
  612 + return false;
  613 + //alert("无法在指定位置生成班次");
  614 + //throw "无法在路牌index=" + lpIndex + ",圈index=" + qIndex + ",班次index=" + bcIndex + "生成班次";
  615 + }
  616 +
  617 + // 2、计算发车间隔
  618 + var _intervalTime = 0;
  619 + for (_i = _i + 1; _i <= lpIndex; _i++) {
  620 + _intervalTime += _internalLpArray[_i].getVerticalMinIntervalTime();
  621 + }
  622 +
  623 + // 3、计算班次并添加班次
  624 + var _kssj = _paramObj.addMinute(_bcObj.getFcTimeObj(), _intervalTime);
  625 + _bcObj = _factory.createBcObj(
  626 + _internalLpArray[lpIndex],
  627 + "normal", _bcObj.isUp(),
  628 + 1, _kssj, _paramObj);
  629 + _bcObj.setGroup(_internalLpArray[lpIndex].getGroup(qIndex));
  630 +
  631 + return _bcObj;
  632 +
  633 + // TODO:这种添加班次的方法,可能造成相邻班次的停站时间问题
  634 + // TODO:主要是由于中标线的问题,但是误差不会很大,
  635 + // TODO:后面有方法直接调整停站时间(所谓的平滑过度时间)
  636 + };
  637 +
  638 + /**
  639 + * 在指定位置生成班次并添加到路牌指定位置中。
  640 + * @param lpIndex 第几个路牌
  641 + * @param qIndex 第几圈
  642 + * @param bcIndex 第几个班次
  643 + */
  644 + var _generateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
  645 + var _bcObj = _generateBc(lpIndex, qIndex, bcIndex);
  646 + _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
  647 +
  648 + };
  649 +
  650 + /**
  651 + * 查找离指定时间最近的前面的班次索引信息
  652 + * @param timeObj 查找时间
  653 + * @param isUp 是否上行
  654 + * @returns [{路牌index},{圈index},{班次index}]
  655 + */
  656 + var _findUpClosedBcIndexWithTime = function(timeObj, isUp) {
  657 +
  658 + // dododo
  659 +
  660 + var _lpObj;
  661 + var _groupObj;
  662 + var _bcObj;
  663 + var _i;
  664 + var _j;
  665 + var timediff; // 时间差取绝对值
  666 +
  667 + var _lpIndex;
  668 + var _up_qIndex;
  669 + var _up_bIndex;
  670 +
  671 + for (_i = 0; _i < _qCount; _i++) {
  672 + for (_j = 0; _j < _internalLpArray.length; _j++) {
  673 + _lpObj = _internalLpArray[_j];
  674 + _groupObj = _lpObj.getGroup(_i);
  675 + _bcObj = isUp ? _groupObj.getBc1() : _groupObj.getBc2();
  676 + if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
  677 + _bcObj = _generateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
  678 + }
  679 + if (_bcObj) {
  680 + if (timeObj.diff(_bcObj.getFcTimeObj()) >= 0) {
  681 + if (!timediff) {
  682 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  683 + _lpIndex = _j;
  684 + _up_qIndex = _i;
  685 + _up_bIndex = isUp == _qIsUp ? 0 : 1;
  686 + } else {
  687 + if (timeObj.diff(_bcObj.getFcTimeObj()) < timediff) {
  688 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  689 + _lpIndex = _j;
  690 + _up_qIndex = _i;
  691 + _up_bIndex = isUp == _qIsUp ? 0 : 1;
  692 + }
  693 + }
  694 + }
  695 + }
  696 + }
  697 + }
  698 +
  699 + if (_lpIndex == undefined) {
  700 + return false;
  701 + }
  702 +
  703 + var bcindex = [];
  704 + bcindex.push(_lpIndex);
  705 + bcindex.push(_up_qIndex);
  706 + bcindex.push(_up_bIndex);
  707 +
  708 + return bcindex;
  709 + };
  710 +
  711 + /**
  712 + * 查找离指定时间最近的后面的班次索引信息
  713 + * @param timeObj 查找时间
  714 + * @param isUp 是否上行
  715 + * @returns [{路牌index},{圈index},{班次index}]
  716 + */
  717 + var _findDownClosedBcIndexWithTime = function(timeObj, isUp) {
  718 + var _lpObj;
  719 + var _groupObj;
  720 + var _bcObj;
  721 + var _i;
  722 + var _j;
  723 + var timediff; // 时间差取绝对值
  724 +
  725 + var _lpIndex;
  726 + var _down_qIndex;
  727 + var _down_bIndex;
  728 +
  729 + var flag;
  730 +
  731 + for (_i = 0; _i < _qCount; _i++) {
  732 + for (_j = 0; _j < _internalLpArray.length; _j++) {
  733 + _lpObj = _internalLpArray[_j];
  734 + _groupObj = _lpObj.getGroup(_i);
  735 + _bcObj = isUp ? _groupObj.getBc1() : _groupObj.getBc2();
  736 + if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
  737 + _bcObj = _generateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
  738 + }
  739 + if (_bcObj) {
  740 + //console.log("timeobj -> bcobj diff flag " +
  741 + // timeObj.format("HH:mm") + "->" +
  742 + // _bcObj.getFcTimeObj().format("HH:mm") +
  743 + // timeObj.diff(_bcObj.getFcTimeObj()) +
  744 + // (timeObj.diff(_bcObj.getFcTimeObj()) <= 0)
  745 + //);
  746 +
  747 + flag = (timeObj.diff(_bcObj.getFcTimeObj())) <= 0;
  748 +
  749 + if (flag) {
  750 + if (!timediff) {
  751 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  752 + _lpIndex = _j;
  753 + _down_qIndex = _i;
  754 + _down_bIndex = isUp == _qIsUp ? 0 : 1;
  755 + } else {
  756 + if ((timeObj.diff(_bcObj.getFcTimeObj())) > timediff) {
  757 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  758 + _lpIndex = _j;
  759 + _down_qIndex = _i;
  760 + _down_bIndex = isUp == _qIsUp ? 0 : 1;
  761 + }
  762 + }
  763 + }
  764 + }
  765 + }
  766 + }
  767 +
  768 + if (_lpIndex == undefined) {
  769 + return false;
  770 + }
  771 +
  772 + var bcindex = [];
  773 + bcindex.push(_lpIndex);
  774 + bcindex.push(_down_qIndex);
  775 + bcindex.push(_down_bIndex);
  776 +
  777 + return bcindex;
  778 + };
  779 +
  780 + return {
  781 + //------------- 布局初始化方法 ------------//
  782 + /**
  783 + * 初始化数据,使用标线初始化
  784 + */
  785 + fnInitDataWithBxLayout: function() {
  786 + // 初始化布局1,构造上标线,计算圈数,把上标线数据放入第一个路牌中
  787 + _fnInitFun1();
  788 + // 初始化布局2,从上标线的某个班次开始,构造所有路牌的早高峰班次,晚高峰班次,计算路牌在各个圈中的间隔
  789 + _fnInitFun2();
  790 + // 初始化布局3,计算连班分班路牌分布
  791 + _fnInitFun3();
  792 + // 初始化布局4,计算中标线位置
  793 + _fnInitFun4();
  794 +
  795 + },
  796 +
  797 + /**
  798 + * 调整高峰班次,
  799 + * 初始化生成早高峰,晚高峰班次并不准确,因为根据高峰时间段,并不在一个完整圈内,应该是在两个或多个圈之间
  800 + * 当初始化定好布局后(上标线,中标线),然后确定每个路牌的班型(连班,分班,5休2分班)后
  801 + * 然后重新计算框在高峰时间段内的班次索引,不足的添加,之前多加的删除(只删除分班路牌上的)
  802 + * @param isZgf 是否早高峰
  803 + * @param isUp 是否上行
  804 + */
  805 + fnAdjustGfbc : function(isZgf, isUp) {
  806 + var oStartTime; // 开始时间
  807 + var oEndTime; // 结束时间
  808 + var iStartBcIndex; // 开始班次索引
  809 + var iEndBcIndex; // 结束班次索引
  810 +
  811 + oStartTime = isZgf ? _paramObj.getMPeakStartTimeObj() : _paramObj.getEPeakStartTimeObj();
  812 + oEndTime = isZgf ? _paramObj.getMPeakEndTimeObj() : _paramObj.getEPeakEndTimeObj();
  813 +
  814 + aStartBcIndex = _findUpClosedBcIndexWithTime(oStartTime, isUp);
  815 + aEndBcIndex = _findDownClosedBcIndexWithTime(oEndTime, isUp);
  816 +
  817 + var iLpIndex;
  818 + var iQIndex;
  819 + var iBcIndex;
  820 + var iQInternelCount; // 高峰时间段中间包含的圈数
  821 + var i;
  822 + var j;
  823 +
  824 + var oLp;
  825 +
  826 + if (aStartBcIndex && aEndBcIndex) {
  827 + iLpIndex = aStartBcIndex[0];
  828 + iQIndex = aStartBcIndex[1];
  829 + iBcIndex = aStartBcIndex[2];
  830 +
  831 + // 处理头
  832 + // 删除头部多余班次
  833 + for (j = 0; j < iLpIndex; j++) {
  834 + oLp = _internalLpArray[j];
  835 + if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
  836 + oLp.removeBc(iQIndex, iBcIndex);
  837 + }
  838 + }
  839 +
  840 + for (j = iLpIndex; j < _internalLpArray.length; j++) {
  841 + oLp = _internalLpArray[j];
  842 + if (!oLp.getBc(iQIndex, iBcIndex)) {
  843 + _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
  844 + }
  845 + }
  846 +
  847 + // 处理中间
  848 + iQInternelCount = aEndBcIndex[1] - aStartBcIndex[1] - 1;
  849 + for (i = 1; i <= iQInternelCount; i++) {
  850 + oLp = _internalLpArray[iQIndex + i];
  851 + if (!oLp.getBc(iQIndex + i, iBcIndex)) {
  852 + _fnGenerateBcAndSetBc(i, iQIndex + i, iBcIndex);
  853 + }
  854 + }
  855 +
  856 + // 处理尾部
  857 + iLpIndex = aEndBcIndex[0];
  858 + iQIndex = aEndBcIndex[1];
  859 + iBcIndex = aEndBcIndex[2];
  860 +
  861 + // 删除尾部多余的班次
  862 + for (j = iLpIndex; j < _internalLpArray.length; j++) {
  863 + oLp = _internalLpArray[j];
  864 + if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
  865 + oLp.removeBc(iQIndex, iBcIndex);
  866 + }
  867 + }
  868 +
  869 + if (aStartBcIndex[1] != aEndBcIndex[1]) { // 指定时间范围跨圈
  870 + for (j = 0; j < iLpIndex; j++) {
  871 + oLp = _internalLpArray[j];
  872 + if (!oLp.getBc(iQIndex, iBcIndex)) {
  873 + _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
  874 + }
  875 + }
  876 + } else {
  877 + // 不跨圈,不用处理,处理头的时候已经加了
  878 + }
  879 +
  880 + }
  881 +
  882 + },
  883 +
  884 + /**
  885 + * 按照营运时间要求补充班次,
  886 + * 早高峰7:45分以前出场运营,
  887 + * 晚高峰16:10分以前出场运营
  888 + */
  889 + fnCalcuLpBc_yy: function() {
  890 + // 补班次的时候,针对的是分班班型
  891 + var i;
  892 + var _oLp;
  893 + var _oBc;
  894 + var _aMinBcIndex;
  895 + var _aMaxBcIndex;
  896 +
  897 + var _qIndex;
  898 + var _bIndex;
  899 +
  900 + var _zgfCDate = _paramObj.toTimeObj("7:45");
  901 + var _wgfCDate = _paramObj.toTimeObj("16:10");
  902 + var _ccsj;
  903 +
  904 + for (i = 0; i < _internalLpArray.length; i++) {
  905 + _oLp = _internalLpArray[i];
  906 + if (_oLp.isBxFb()) { // 分班路牌
  907 + // 早高峰部分
  908 + _aMinBcIndex = _oLp.getMinBcObjPosition();
  909 + _qIndex = _aMinBcIndex[0];
  910 + _bIndex = _aMinBcIndex[1];
  911 + _oBc = _oLp.getBc(_qIndex, _bIndex);
  912 + if (_qIsUp) {
  913 + _ccsj = _bIndex == 0 ?
  914 + _paramObj.getUpOutTime() :
  915 + _paramObj.getDownOutTime();
  916 + } else {
  917 + _ccsj = _bIndex == 0 ?
  918 + _paramObj.getDownOutTime() :
  919 + _paramObj.getUpOutTime();
  920 + }
  921 + if (_zgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
  922 + _fnGenerateBcAndSetBc(
  923 + i,
  924 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  925 + _bIndex == 0 ? 1 : 0
  926 + )
  927 + }
  928 +
  929 + // 晚高峰部分
  930 + _aMaxBcIndex = _oLp.getMaxBcObjPosition();
  931 + _qIndex = _aMaxBcIndex[0];
  932 + _bIndex = _aMaxBcIndex[1];
  933 + _oBc = _oLp.getBc(
  934 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  935 + _bIndex == 0 ? 1 : 0
  936 + );
  937 + if (!_oBc) { // 前一个班次不存在,再判定加不加
  938 + _oBc = _oLp.getBc(_qIndex, _bIndex);
  939 + if (_qIsUp) {
  940 + _ccsj = _bIndex == 0 ?
  941 + _paramObj.getUpOutTime() :
  942 + _paramObj.getDownOutTime();
  943 + } else {
  944 + _ccsj = _bIndex == 0 ?
  945 + _paramObj.getDownOutTime() :
  946 + _paramObj.getUpOutTime();
  947 + }
  948 + if (_wgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
  949 + _fnGenerateBcAndSetBc(
  950 + i,
  951 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  952 + _bIndex == 0 ? 1 : 0
  953 + )
  954 + }
  955 + }
  956 + }
  957 + }
  958 + },
  959 +
  960 + /**
  961 + * 补充做5休2的班型班次。
  962 + * 1、确认5_2班型大致多少圈(小数点过.7进位)
  963 + * 2、获取当前5_2两端车次链的信息,每段的班次数目,还差几个班次没加
  964 + * 3、如果前面的车次链班次少,则从前面的车次链开始加
  965 + * 4、如果车次链班次数一样,从从后面的车次链开始加
  966 + * 5、加班次时都是往车次链前方加
  967 + * 6、如果前面车次链不能再加班次了,从后面车次链加
  968 + */
  969 + fnCalcuLpBx_5_2: function() {
  970 + // 计算做5休2班型所需的班次数
  971 + var iBxBcount = _aBxDesc[6].fBcCount;
  972 + if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
  973 + iBxBcount = Math.floor(iBxBcount) + 1;
  974 + } else {
  975 + iBxBcount = Math.floor(iBxBcount);
  976 + }
  977 +
  978 + var i;
  979 + var j;
  980 + var oLp;
  981 + var iAddBcCount;
  982 + var oBcChain1;
  983 + var oBcChain2;
  984 + var iQindex;
  985 + var iBindex;
  986 +
  987 + for (i = 0; i < _internalLpArray.length; i++) {
  988 + oLp = _internalLpArray[i];
  989 + if (oLp.isBxFb5_2()) {
  990 + iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
  991 + for (j = 1; j <= iAddBcCount; j++) {
  992 + oBcChain1 = oLp.fnGetBcChainInfo(0);
  993 + oBcChain2 = oLp.fnGetBcChainInfo(1);
  994 +
  995 + if (oBcChain1.bcount < oBcChain2.bcount) {
  996 + iQindex = oBcChain1.s_b == 0 ? oBcChain1.s_q - 1 : oBcChain1.s_q;
  997 + iBindex = oBcChain1.s_b == 0 ? 1 : 0;
  998 + // 往车次链往前不能加,就往后加
  999 + if (_fnGenerateBc(i, iQindex, iBindex)) {
  1000 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1001 + } else {
  1002 + iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
  1003 + iBindex = oBcChain1.e_b == 0 ? 1 : 0;
  1004 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1005 + }
  1006 +
  1007 + } else if (oBcChain1.bcount > oBcChain2.bcount) {
  1008 + iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
  1009 + iBindex = oBcChain2.s_b == 0 ? 1 : 0;
  1010 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1011 + } else {
  1012 + iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
  1013 + iBindex = oBcChain2.s_b == 0 ? 1 : 0;
  1014 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1015 + }
  1016 + }
  1017 + }
  1018 + }
  1019 +
  1020 + },
  1021 +
  1022 + /**
  1023 + * 补其他分班班型班次。
  1024 + * 从车次链的后面开始加
  1025 + */
  1026 + fnCalcuLpBx_other: function() {
  1027 + // TODO:暂时使用做2休1的班型
  1028 + // 计算做5休2班型所需的班次数
  1029 + var iBxBcount = _aBxDesc[4].fBcCount;
  1030 + if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
  1031 + iBxBcount = Math.floor(iBxBcount) + 1;
  1032 + } else {
  1033 + iBxBcount = Math.floor(iBxBcount);
  1034 + }
  1035 +
  1036 + var i;
  1037 + var j;
  1038 + var oLp;
  1039 + var iAddBcCount;
  1040 + var oBcChain1;
  1041 + var oBcChain2;
  1042 + var iQindex;
  1043 + var iBindex;
  1044 +
  1045 + for (i = 0; i < _internalLpArray.length; i++) {
  1046 + oLp = _internalLpArray[i];
  1047 + if (oLp.isBxFb() && !oLp.isBxFb5_2()) {
  1048 + iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
  1049 + for (j = 1; j <= iAddBcCount; j++) {
  1050 + oBcChain1 = oLp.fnGetBcChainInfo(0);
  1051 + oBcChain2 = oLp.fnGetBcChainInfo(1);
  1052 +
  1053 + if (oBcChain1.bcount < oBcChain2.bcount) {
  1054 + iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
  1055 + iBindex = oBcChain1.e_b == 0 ? 1 : 0;
  1056 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1057 + } else if (oBcChain1.bcount > oBcChain2.bcount) {
  1058 + iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
  1059 + iBindex = oBcChain2.e_b == 0 ? 1 : 0;
  1060 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1061 + } else {
  1062 + iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
  1063 + iBindex = oBcChain2.e_b == 0 ? 1 : 0;
  1064 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1065 + }
  1066 + }
  1067 + }
  1068 + }
  1069 +
  1070 + },
  1071 +
  1072 + /**
  1073 + * 补充连班路牌班次。
  1074 + * 1、上标线,中标线中间的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向上标线起始班次靠拢
  1075 + * 2、中标线以下的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向中标线起始班次靠拢
  1076 + */
  1077 + fnCalcuLpBx_lb: function() {
  1078 + // 补充连班的班次,参照上标线,中标线补充不足的班次
  1079 +
  1080 + var aLbLpindexes = []; // 除上标线,中标线的连班路牌索引
  1081 + var i;
  1082 + for (i = 0; i < _internalLpArray.length; i++) {
  1083 + if (_internalLpArray[i].isBxLb() && i != 0 && i != _iZbx_lpIndex) {
  1084 + aLbLpindexes.push(i);
  1085 + }
  1086 + }
  1087 +
  1088 + var oEndsj = // 结束时间
  1089 + _paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj()) ?
  1090 + _paramObj.getDownLastDTimeObj() :
  1091 + _paramObj.getUpLastDtimeObj();
  1092 +
  1093 + var oLp;
  1094 + var aMinbcPos;
  1095 + var oBc;
  1096 + var j;
  1097 + var iTempBcIndex;
  1098 +
  1099 + // 1、从最小班次开始,往后补充班次
  1100 + for (i = 0; i < aLbLpindexes.length; i++) {
  1101 + oLp = _internalLpArray[aLbLpindexes[i]];
  1102 +
  1103 + // 最小班次索引
  1104 + aMinbcPos = oLp.getMinBcObjPosition();
  1105 + // 使用纵向分隔补充班次,从最小班次向后补
  1106 + iTempBcIndex = aMinbcPos[1] == 0 ? 1 : 0;
  1107 + j = iTempBcIndex == 0 ? aMinbcPos[0] + 1 : aMinbcPos[0];
  1108 +
  1109 + while (j < _qCount) {
  1110 + while (iTempBcIndex <= 1) {
  1111 + oBc = _fnGenerateBc(aLbLpindexes[i], j, iTempBcIndex);
  1112 + if (oBc &&
  1113 + oBc.getFcTimeObj().isBefore(oEndsj) &&
  1114 + oBc.getArrTimeObj().isBefore(oEndsj)) {
  1115 + oLp.setBc(j, iTempBcIndex, oBc);
  1116 + }
  1117 + iTempBcIndex++;
  1118 + }
  1119 + iTempBcIndex = 0;
  1120 + j++;
  1121 + }
  1122 +
  1123 + }
  1124 +
  1125 + // 2、上标线中标线之间的路牌,从最小的班次往前补充班次
  1126 +
  1127 + // 还要补充缺失的班次,差上标线几个班次要往前补上
  1128 + var iBccount;
  1129 + var iQindex;
  1130 + var iBindex;
  1131 + // 补上标线到中标线之间的连班路牌的班次
  1132 + for (i = 0; i < aLbLpindexes.length; i++) {
  1133 + if (aLbLpindexes[i] > 0 && aLbLpindexes[i] < _iZbx_lpIndex) {
  1134 + oLp = _internalLpArray[aLbLpindexes[i]];
  1135 + aMinbcPos = oLp.getMinBcObjPosition();
  1136 + iQindex = aMinbcPos[0];
  1137 + iBindex = aMinbcPos[1];
  1138 + iBccount = (iQindex - 1) * 2 + iBindex; // 距离上标线起始站点差几个班次
  1139 + for (j = 0; j < iBccount; j++) {
  1140 + if (iBindex == 0) {
  1141 + iQindex --;
  1142 + iBindex = 1;
  1143 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1144 + } else if (iBindex == 1) {
  1145 + iBindex --;
  1146 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1147 + }
  1148 + }
  1149 +
  1150 + }
  1151 +
  1152 + }
  1153 +
  1154 + // 3、中标线之后的路牌,从最小的班次往前补充班次
  1155 +
  1156 + // 补中标线以下的连班路牌的班次
  1157 + for (i = 0; i < aLbLpindexes.length; i++) {
  1158 + if (aLbLpindexes[i] > _iZbx_lpIndex) {
  1159 + oLp = _internalLpArray[aLbLpindexes[i]];
  1160 + aMinbcPos = oLp.getMinBcObjPosition();
  1161 + iQindex = aMinbcPos[0];
  1162 + iBindex = aMinbcPos[1];
  1163 + iBccount = (iQindex - 0) * 2 + iBindex - 1; // 距离上标线起始站点差几个班次
  1164 + for (j = 0; j < iBccount; j++) {
  1165 + if (iBindex == 0) {
  1166 + iQindex --;
  1167 + iBindex = 1;
  1168 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1169 + } else if (iBindex == 1) {
  1170 + iBindex --;
  1171 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1172 + }
  1173 + }
  1174 + }
  1175 + }
  1176 +
  1177 + },
  1178 +
  1179 + /**
  1180 + * 计算末班车(一般都落在连班班型上,因为按照现在的布局方法,分班路牌不会一直连到最后)。
  1181 + * 1、确定末班车早的班次
  1182 + * 2、从后往前找到与这个班次最匹配的班次的位置(第几个路牌,第几圈,第几个班次),然后覆盖
  1183 + * 3、从第2步找的位置,往上找与另一个末班车匹配的班次位置,然后覆盖
  1184 + */
  1185 + fnCalcuLastBc: function() {
  1186 + //-------------------- 1、确定末班车早的方向,时间 -----------------------//
  1187 + var _oLastTime;
  1188 + var _bLastIsUp;
  1189 + if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
  1190 + _oLastTime = _paramObj.getUpLastDtimeObj();
  1191 + _bLastIsUp = true;
  1192 + } else {
  1193 + _oLastTime = _paramObj.getDownLastDTimeObj();
  1194 + _bLastIsUp = false;
  1195 + }
  1196 +
  1197 + //-------------------- 2、确定比 _oLastTime 小或者等于的班次位置,并修改班次时间到末班车时间 -----------------//
  1198 + var i;
  1199 + var j;
  1200 + var _oBc;
  1201 + var _oLp;
  1202 + var _aBcIndex;
  1203 +
  1204 + for (i = _qCount - 1; i >= 0; i--) {
  1205 + if (_aBcIndex) {
  1206 + break;
  1207 + }
  1208 + // 从大到小找到第一个合适的班次索引
  1209 + for (j = _internalLpArray.length - 1; j >= 0; j--) {
  1210 + _oLp = _internalLpArray[j];
  1211 + if (_oLp.isBxLb()) {
  1212 + _oBc = _oLp.getBc(i, _qIsUp == _bLastIsUp ? 0 : 1);
  1213 + }
  1214 + if (_oBc != undefined && _oBc.getFcTimeObj().isBefore(_oLastTime)) {
  1215 + _aBcIndex = [];
  1216 + _aBcIndex.push(j); // 路牌索引
  1217 + _aBcIndex.push(i); // 圈索引
  1218 + _aBcIndex.push(_qIsUp == _bLastIsUp ? 0 : 1); // 班次索引
  1219 + break;
  1220 + }
  1221 + }
  1222 + }
  1223 +
  1224 + //-------------------- 3、预估哪个个班次离末班最近,用末班替换,并删除后面的多余班次 -----------------//
  1225 + // 第2步找到的班次不一定是最适合的,需要把之后的班次模拟出来再比较一下
  1226 + var _aBcIndexes = []; // 里面放对象 {lpIndex,qIndex,bcIndex,fcsjTime}
  1227 + _oBc = undefined;
  1228 + for (i = _aBcIndex[0]; i < _internalLpArray.length; i++) {
  1229 + _oLp = _internalLpArray[i];
  1230 + if (_oLp.isBxLb()) {
  1231 + _oBc = _oLp.getBc(_aBcIndex[1], _aBcIndex[2]);
  1232 + if (_oBc == undefined) {
  1233 + _oBc = _fnGenerateBc(i, _aBcIndex[1], _aBcIndex[2]);
  1234 + }
  1235 + _aBcIndexes.push({
  1236 + lpIndex: i,
  1237 + qIndex: _aBcIndex[1],
  1238 + bcIndex: _aBcIndex[2],
  1239 + bcObj: _oBc
  1240 + })
  1241 + }
  1242 + }
  1243 + var _oBcIndex_find; // 第几个路牌离末班车最近
  1244 + for (i = _aBcIndexes.length - 1; i >= 0; i--) {
  1245 + if (_aBcIndexes[i].bcObj.getFcTimeObj().isBefore(_oLastTime)) {
  1246 + _oBcIndex_find = _aBcIndexes[i];
  1247 + break;
  1248 + }
  1249 + }
  1250 + // 替换成末班车
  1251 + _oBc = _oBcIndex_find.bcObj;
  1252 + _oBc.addMinuteToFcsj(_oLastTime.diff(_oBc.getFcTimeObj(), "m"));
  1253 + _internalLpArray[_oBcIndex_find.lpIndex].setBc(
  1254 + _oBcIndex_find.qIndex, _oBcIndex_find.bcIndex, _oBc
  1255 + );
  1256 +
  1257 + // 删除多余班次呢
  1258 + for (i = _oBcIndex_find.lpIndex + 1; i < _internalLpArray.length; i++) {
  1259 + _internalLpArray[i].removeBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex);
  1260 + }
  1261 +
  1262 + //---------------------- 4、从第3步找到的位置,开始往上找,确定另一个末班车,并删除后面多余的班次 -------------//
  1263 + // 因为另一个末班车时间晚,肯定在后面,并且必须在之前的路牌
  1264 + // 如果在之后的路牌,则意味着之前那个末班车位置不对,连班连起来会有两个之前的末班车
  1265 + // 计算大的末班车时间
  1266 + if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
  1267 + _oLastTime = _paramObj.getDownLastDTimeObj();
  1268 + _bLastIsUp = false;
  1269 + } else {
  1270 + _oLastTime = _paramObj.getUpLastDtimeObj();
  1271 + _bLastIsUp = true;
  1272 + }
  1273 + _aBcIndexes = [];
  1274 + for (i = _oBcIndex_find.lpIndex; i >=0; i--) {
  1275 + _oLp = _internalLpArray[i];
  1276 + if (_oLp.isBxLb()) {
  1277 + _oBc = _oLp.getBc(
  1278 + _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
  1279 + _oBcIndex_find.bcIndex == 0 ? 1 : 0
  1280 + );
  1281 + if (_oBc == undefined) {
  1282 + _oBc = _fnGenerateBc(
  1283 + i,
  1284 + _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
  1285 + _oBcIndex_find.bcIndex == 0 ? 1 : 0
  1286 + );
  1287 + }
  1288 + if (!_oBc) { // 纵向生成班次失败,用横向生成班次,发车时间取前一班次的到达时间加停战时间
  1289 + _oBc = _factory.createBcObj(
  1290 + _oLp,
  1291 + "normal",
  1292 + _bLastIsUp,
  1293 + 3,
  1294 + _oLp.getBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex).getArrTimeObj(),
  1295 + _paramObj
  1296 + );
  1297 +
  1298 + }
  1299 + _aBcIndexes.push({
  1300 + lpIndex: i,
  1301 + qIndex: _oBcIndex_find.bcIndex == 0 ? _oBcIndex_find.qIndex : _oBcIndex_find.qIndex + 1,
  1302 + bcIndex: _oBcIndex_find.bcIndex == 0 ? 1 : 0,
  1303 + bcObj: _oBc
  1304 + })
  1305 + }
  1306 + }
  1307 +
  1308 + console.log(_aBcIndexes);
  1309 +
  1310 + _oBcIndex_find = _aBcIndexes[0];
  1311 +
  1312 + for (i = 0; i < _aBcIndexes.length; i++) {
  1313 + if (_aBcIndexes[i].bcObj.getFcTimeObj().isBefore(_oLastTime)) {
  1314 + _oBcIndex_find = _aBcIndexes[i];
  1315 + break;
  1316 + }
  1317 + }
  1318 + // 替换成末班车
  1319 + _oBc = _oBcIndex_find.bcObj;
  1320 + _oBc.addMinuteToFcsj(_oLastTime.diff(_oBc.getFcTimeObj(), "m"));
  1321 + _internalLpArray[_oBcIndex_find.lpIndex].setBc(
  1322 + _oBcIndex_find.qIndex, _oBcIndex_find.bcIndex, _oBc
  1323 + );
  1324 +
  1325 + // 删除多余班次呢
  1326 + for (i = _oBcIndex_find.lpIndex + 1; i < _internalLpArray.length; i++) {
  1327 + _internalLpArray[i].removeBc(_oBcIndex_find.qIndex, _oBcIndex_find.bcIndex);
  1328 + }
  1329 +
  1330 +
  1331 + },
  1332 +
  1333 + /**
  1334 + * 添加吃饭班次。
  1335 + */
  1336 + fnCalcuEatBc: function() {
  1337 + // 吃午饭时间范围,10:15 到 12:15
  1338 + // 吃晚饭时间范围,18:00 到 19:00
  1339 +
  1340 + if (!_paramObj.fnIsEat()) {
  1341 + return;
  1342 + }
  1343 +
  1344 + // 午饭index
  1345 + var aLEIndex;
  1346 + // 晚饭index
  1347 + var aDEIndex;
  1348 +
  1349 + // 所有吃饭都默认在一个方向,两个方向暂时不考虑
  1350 + if (_paramObj.fnIsUpEat()) {
  1351 + aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), true, false);
  1352 + aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), true, false);
  1353 + } else {
  1354 + aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), false, true);
  1355 + aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), false, true);
  1356 + }
  1357 +
  1358 + // 午饭第几圈,第几个班次
  1359 + var iLEQIndex = aLEIndex[0];
  1360 + var iLEBIndex = aLEIndex[1];
  1361 + // 晚饭第几圈,第几个班次
  1362 + var iDEQIndex = aDEIndex[0];
  1363 + var iDEBIndex = aDEIndex[1];
  1364 +
  1365 + // 注意,本模型只有连班才有吃饭
  1366 +
  1367 + var i;
  1368 + var oLp;
  1369 + var aLbIndex = []; // 连班班型的路牌索引
  1370 + for (i = 0; i < _internalLpArray.length; i++) {
  1371 + oLp = _internalLpArray[i];
  1372 + if (oLp.isBxLb()) {
  1373 + aLbIndex.push(i);
  1374 + }
  1375 + }
  1376 +
  1377 + var iLTime;
  1378 + var iDtime;
  1379 + var j;
  1380 + for (i = 0; i < aLbIndex.length; i++) {
  1381 + oLp = _internalLpArray[aLbIndex[i]];
  1382 +
  1383 + // 午饭
  1384 + iLTime = oLp.fnAddEatBc(iLEQIndex, iLEBIndex, _factory, _paramObj);
  1385 + // 晚饭
  1386 + iDtime = oLp.fnAddEatBc(iDEQIndex, iDEBIndex, _factory, _paramObj);
  1387 +
  1388 + if (i == aLbIndex.length - 1) {
  1389 + for (j = aLbIndex[i]; j < _internalLpArray.length; j++) {
  1390 + oLp = _internalLpArray[j];
  1391 + if (oLp.isBxFb()) { // 5休2班型不调整
  1392 + // 修正午饭之后路牌班次的发车时间
  1393 + oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
  1394 + oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
  1395 + }
  1396 + }
  1397 + } else {
  1398 + for (j = aLbIndex[i]; j < aLbIndex[i + 1]; j++) {
  1399 + oLp = _internalLpArray[j];
  1400 + if (oLp.isBxFb()) {
  1401 + // 修正午饭之后路牌班次的发车时间
  1402 + oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
  1403 + oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
  1404 + }
  1405 + }
  1406 + }
  1407 + }
  1408 +
  1409 + },
  1410 +
  1411 + /**
  1412 + * 补每个路牌的其他班次(进出场,例保班次)。
  1413 + */
  1414 + fnCalcuOtherBc: function() {
  1415 + var i;
  1416 + var _lpObj;
  1417 + var _minBcIndex;
  1418 + var _maxBcIndex;
  1419 + var _minBc;
  1420 + var _maxBc;
  1421 + var _otherbc = [];
  1422 +
  1423 + for (i = 0; i < _internalLpArray.length; i++) {
  1424 + _lpObj = _internalLpArray[i];
  1425 + _minBcIndex = _lpObj.getMinBcObjPosition();
  1426 + _maxBcIndex = _lpObj.getMaxBcObjPosition();
  1427 + _minBc = _lpObj.getBc(_minBcIndex[0], _minBcIndex[1]);
  1428 + _maxBc = _lpObj.getBc(_maxBcIndex[0], _maxBcIndex[1]);
  1429 +
  1430 + _otherbc = [];
  1431 + //_otherbc.push(_factory.createBcObj(
  1432 + // _lpObj, "bd", true, 1,
  1433 + // _minBc.getFcTimeObj(),
  1434 + // _paramObj
  1435 + //));
  1436 + _otherbc.push(_factory.createBcObj(
  1437 + _lpObj, "out", true, 1,
  1438 + _minBc.getFcTimeObj(),
  1439 + _paramObj
  1440 + ));
  1441 +
  1442 + _maxBc.setArrTimeObj(_paramObj.addMinute(_maxBc.getFcTimeObj(), _maxBc.getBcTime()));
  1443 + _maxBc.setStopTime(0);
  1444 + _otherbc.push(_factory.createBcObj(
  1445 + _lpObj, "in", true, 1,
  1446 + _maxBc.getArrTimeObj(),
  1447 + _paramObj
  1448 + ));
  1449 + //_otherbc.push(_factory.createBcObj(
  1450 + // _lpObj, "lc", true, 1,
  1451 + // _maxBc.getArrTimeObj(),
  1452 + // _paramObj
  1453 + //));
  1454 +
  1455 + _lpObj.addOtherBcArray(_otherbc);
  1456 + }
  1457 +
  1458 + },
  1459 +
  1460 + /**
  1461 + * 祛除上标线有删除标记的班次。
  1462 + */
  1463 + fnRemoveDelFlagBc: function() {
  1464 + var oLp = _internalLpArray[0];
  1465 + var aMinBcIndex = oLp.getMinBcObjPosition();
  1466 + oLp.removeBc(aMinBcIndex[0], aMinBcIndex[1]);
  1467 +
  1468 + var aMaxBcIndex = oLp.getMaxBcObjPosition();
  1469 + if (oLp.getBc(aMaxBcIndex[0], aMaxBcIndex[1]).fnIsDelFlag()) {
  1470 + oLp.removeBc(aMaxBcIndex[0], aMaxBcIndex[1]);
  1471 + }
  1472 + },
  1473 +
  1474 + /**
  1475 + * 调整班次纵向间隔(发车时间调整)。
  1476 + * 1、只调整分班班次的发车时间
  1477 + * 2、调整每两个连班之间的分班班次组
  1478 + * 3、如果不是连续的班次才调整
  1479 + */
  1480 + fnAdjust_vertical_bc_interval: function() {
  1481 + var i;
  1482 + var j;
  1483 + var iBIndex = 0;
  1484 + var oLbGroup = {};
  1485 + var oLp;
  1486 + for (i = 0; i < _qCount; i++) {
  1487 + while (iBIndex <= 1) {
  1488 + oLbGroup[i + "_" + iBIndex] = [];
  1489 + for (j = 0; j < _internalLpArray.length; j++) {
  1490 + oLp = _internalLpArray[j];
  1491 + if (oLp.isBxLb()) {
  1492 + if (oLp.getBc(i, iBIndex)) {
  1493 + oLbGroup[i + "_" + iBIndex].push(j);
  1494 + }
  1495 + }
  1496 + }
  1497 + if (oLbGroup[i + "_" + iBIndex].length == 1) {
  1498 + oLbGroup[i + "_" + iBIndex] = [];
  1499 + }
  1500 +
  1501 + iBIndex ++;
  1502 + }
  1503 + iBIndex = 0;
  1504 + }
  1505 +
  1506 + //console.log(oLbGroup);
  1507 +
  1508 + var sKey;
  1509 + var iQindex;
  1510 + var iBindex;
  1511 + var aBcLb = [];
  1512 +
  1513 + var oLbGroup_m = {};
  1514 + var aLbGroup = [];
  1515 +
  1516 +
  1517 + // 计算需要调整的连班区间
  1518 + for (sKey in oLbGroup) {
  1519 + iQindex = sKey.split('_')[0];
  1520 + iBindex = sKey.split('_')[1];
  1521 + oLbGroup_m[sKey] = [];
  1522 + for (i = 0; i < oLbGroup[sKey].length - 1; i++) {
  1523 + aBcLb = [];
  1524 + for (j = oLbGroup[sKey][i] + 1; j <= oLbGroup[sKey][i + 1] - 1; j++) {
  1525 + oLp = _internalLpArray[j];
  1526 + if (oLp.getBc(iQindex, iBindex)) {
  1527 + aBcLb.push(j);
  1528 + }
  1529 + }
  1530 + if (aBcLb.length != 0 && aBcLb.length < (oLbGroup[sKey][i + 1] - oLbGroup[sKey][i] - 1)) {
  1531 + aLbGroup = [];
  1532 + aLbGroup.push(oLbGroup[sKey][i]);
  1533 + aLbGroup.push(oLbGroup[sKey][i + 1]);
  1534 + aLbGroup.push(aBcLb);
  1535 + oLbGroup_m[sKey].push(aLbGroup);
  1536 + }
  1537 + }
  1538 + }
  1539 +
  1540 + console.log(oLbGroup_m);
  1541 +
  1542 + var iStartLpIndex;
  1543 + var iEndLpIndex;
  1544 + var iDCount;
  1545 + var iDiffTime;
  1546 +
  1547 + var iC1;
  1548 + var iC2;
  1549 + var oKssj;
  1550 +
  1551 + for (sKey in oLbGroup_m) {
  1552 + iQindex = sKey.split('_')[0];
  1553 + iBindex = sKey.split('_')[1];
  1554 +
  1555 + for (i = 0; i < oLbGroup_m[sKey].length; i++) {
  1556 + aLbGroup = oLbGroup_m[sKey][i];
  1557 +
  1558 + iStartLpIndex = aLbGroup[0];
  1559 + iEndLpIndex = aLbGroup[1];
  1560 + iDCount = aLbGroup[2].length + 1;
  1561 +
  1562 + iDiffTime = _internalLpArray[iEndLpIndex].getBc(iQindex, iBindex).getFcTimeObj().diff(
  1563 + _internalLpArray[iStartLpIndex].getBc(iQindex, iBindex).getFcTimeObj(), 'm');
  1564 +
  1565 + iC1 = Math.floor(iDiffTime / iDCount);
  1566 + iC2 = iDiffTime % iDCount;
  1567 + oKssj = _internalLpArray[iStartLpIndex].getBc(iQindex, iBindex).getFcTimeObj();
  1568 +
  1569 + for (j = 1; j <= iDCount - iC2; j++) {
  1570 + if (j - 1 < aLbGroup[2].length) {
  1571 + oKssj = _paramObj.addMinute(oKssj, iC1);
  1572 + _internalLpArray[aLbGroup[2][j - 1]].getBc(
  1573 + iQindex, iBindex).setFcTimeObj(oKssj);
  1574 + }
  1575 + }
  1576 +
  1577 + for (j = 1; j < iC2; j++) {
  1578 + oKssj = _paramObj.addMinute(oKssj, iC1 + 1);
  1579 + _internalLpArray[aLbGroup[2][iDCount - iC2 + j - 1]].getBc(
  1580 + iQindex, iBindex).setFcTimeObj(oKssj);
  1581 + }
  1582 +
  1583 + }
  1584 + }
  1585 +
  1586 + },
  1587 +
  1588 + //------------- 其他方法 -------------//
  1589 + /**
  1590 + * 内部数据转化成显示用的班次数组。
  1591 + */
  1592 + fnToGanttBcArray: function() {
  1593 + var aAllBc = [];
  1594 + var aLpBc = [];
  1595 + var oLp;
  1596 + var i;
  1597 + var j;
  1598 +
  1599 + for (i = 0; i < _internalLpArray.length; i++) {
  1600 + oLp = _internalLpArray[i];
  1601 + aLpBc = [];
  1602 + aLpBc = aLpBc.concat(oLp.getOtherBcArray(), oLp.getBcArray());
  1603 + // 按照发车时间排序
  1604 + aLpBc.sort(function(o1, o2) {
  1605 + if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
  1606 + return -1;
  1607 + } else {
  1608 + return 1;
  1609 + }
  1610 + });
  1611 +
  1612 + // 重新赋值fcno
  1613 + for (j = 0; j < aLpBc.length; j++) {
  1614 + aLpBc[j].fnSetFcno(j + 1);
  1615 + }
  1616 +
  1617 + aAllBc = aAllBc.concat(aLpBc);
  1618 + }
  1619 +
  1620 + var aGanttBc = [];
  1621 + for (i = 0; i < aAllBc.length; i++) {
  1622 + aGanttBc.push(aAllBc[i].toGanttBcObj());
  1623 + }
  1624 +
  1625 + return aGanttBc;
  1626 + }
  1627 +
  1628 + };
  1629 +
1630 1630 };
1631 1631 \ No newline at end of file
... ...
src/main/resources/static/pages/base/timesmodel/js/v2/main_v2.js
1   -/**
2   - * 主类。
3   - */
4   -var Main_v2 = function() {
5   -
6   - // 内部工厂类
7   - var _factoryFun = function() {
8   - return {
9   - // 创建参数
10   - createParameterObj: function(formMap, dataMap) {
11   - var paramObj = ParameterObj();
12   - paramObj.wrap(formMap, dataMap);
13   - return paramObj;
14   - },
15   - // 创建班次对象
16   - createBcObj: function(lpObj, bcType, isUp, fcno, fcTimeObj, paramObj) {
17   - var _bclc = paramObj.calcuTravelLcNumber(isUp, bcType);
18   - var _fcsj = fcTimeObj;
19   - var _bcsj = paramObj.calcuTravelTime(_fcsj, isUp);
20   - var _arrsj = paramObj.addMinute(_fcsj, _bcsj);
21   - var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
22   - var _tccid = paramObj.getTTinfoId();
23   - var _ttinfoid = paramObj.getTTinfoId();
24   - var _xl = paramObj.getXlId();
25   - var _qdz = isUp ? paramObj.getUpQdzObj().id : paramObj.getDownQdzObj().id;
26   - var _zdz = isUp ? paramObj.getUpZdzObj().id : paramObj.getDownZdzObj().id;
27   -
28   - if (bcType == "bd") { // 早例保,传过来的发车时间是第一个班次的发车时间
29   - if (isUp) { // 上行
30   - _fcsj = paramObj.addMinute(
31   - _fcsj,
32   - -(paramObj.getUpOutTime() + paramObj.getLbTime()));
33   - _bcsj = paramObj.getLbTime();
34   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
35   - _stoptime = 0;
36   - } else { // 下行
37   - _fcsj = paramObj.addMinute(
38   - _fcsj,
39   - -(paramObj.getDownOutTime() + paramObj.getLbTime()));
40   - _bcsj = paramObj.getLbTime();
41   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
42   - _stoptime = 0;
43   - }
44   - } else if (bcType == "lc") { // 晚例保,传过来的发车时间是最后一个班次的到达时间
45   - if (isUp) { // 上行
46   - _fcsj = paramObj.addMinute(
47   - _fcsj,
48   - paramObj.getUpInTime());
49   - _bcsj = paramObj.getLbTime();
50   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
51   - _stoptime = 0;
52   - } else { // 下行
53   - _fcsj = paramObj.addMinute(
54   - _fcsj,
55   - paramObj.getDownInTime());
56   - _bcsj = paramObj.getLbTime();
57   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
58   - _stoptime = 0;
59   - }
60   - } else if (bcType == "out") { // 出场,传过来的发车时间是第一个班次的发车时间
61   - if (isUp) { // 上行
62   - _fcsj = paramObj.addMinute(
63   - _fcsj,
64   - -paramObj.getUpOutTime());
65   - _bcsj = paramObj.getUpOutTime();
66   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
67   - _stoptime = 0;
68   - } else { // 下行
69   - _fcsj = paramObj.addMinute(
70   - _fcsj,
71   - -paramObj.getDownOutTime());
72   - _bcsj = paramObj.getDownOutTime();
73   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
74   - _stoptime = 0;
75   - }
76   - } else if (bcType == "in") { // 进场,传过来的发车时间是最后一个班次的到达时间
77   - if (isUp) { // 上行
78   - _bcsj = paramObj.getUpInTime();
79   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
80   - _stoptime = 0;
81   - } else { // 下行
82   - _bcsj = paramObj.getDownInTime();
83   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
84   - _stoptime = 0;
85   - }
86   - } else if (bcType == "cf") { // 吃饭班次
87   - // 以13:00为分界,之前的为午饭,之后的为晚饭
88   - if (fcTimeObj.isBefore(paramObj.toTimeObj("13:00"))) {
89   - _bcsj = paramObj.fnGetLunchTime();
90   - } else {
91   - _bcsj = paramObj.fnGetDinnerTime();
92   - }
93   - _arrsj = paramObj.addMinute(_fcsj, _bcsj);
94   - _stoptime = 0;
95   - }
96   -
97   - var bcParamObj = {};
98   - bcParamObj.bcType = bcType; // 班次类型(normal,in_,out, bd, lc, cf等)
99   - bcParamObj.isUp = isUp; // boolean是否上下行
100   - bcParamObj.fcno = fcno; // 发车顺序号
101   - bcParamObj.fcTimeObj = _fcsj; // 发车时间对象
102   - bcParamObj.bclc = _bclc; // 班次里程
103   - bcParamObj.bcsj = _bcsj; // 班次历时
104   - bcParamObj.arrtime = _arrsj; // 到达时间对象
105   - bcParamObj.stoptime = _stoptime; // 停站时间
106   - bcParamObj.tccid = _tccid; // 停车场id
107   - bcParamObj.ttinfoid = _ttinfoid; // 时刻表id
108   - bcParamObj.xl = _xl; // 线路id
109   - bcParamObj.qdzid = _qdz; // 起点站id
110   - bcParamObj.zdzid = _zdz; // 终点站id
111   -
112   - return new InternalBcObj(lpObj, bcParamObj);
113   - }
114   - };
115   - };
116   - var _factory = _factoryFun();
117   -
118   - // 所有的时间使用moment.js计算
119   -
120   - var _paramObj; // 参数对象
121   -
122   - var _bxDesc = [ // 班型描述
123   - {'type':'六工一休','hoursV':6.66, 'minueV':'6:40', 'qcount': 0, 'avertime': 0},
124   - {'type':'五工一休','hoursV':6.85, 'minueV':'6:51', 'qcount': 0, 'avertime': 0},
125   - {'type':'四工一休','hoursV':7.14, 'minueV':'7:08', 'qcount': 0, 'avertime': 0},
126   - {'type':'三工一休','hoursV':7.61, 'minueV':'7:37', 'qcount': 0, 'avertime': 0},
127   - {'type':'二工一休','hoursV':8.57, 'minueV':'8:34', 'qcount': 0, 'avertime': 0},
128   - {'type':'一工一休','hoursV':11.42, 'minueV':'11:25', 'qcount': 0, 'avertime': 0},
129   - {'type':'五工二休','hoursV':7.99, 'minueV':'8:00', 'qcount': 0, 'avertime': 0},
130   - {'type':'无工休', 'hoursV':5.43, 'minueV':'5:43', 'qcount': 0, 'avertime': 0}
131   - ];
132   -
133   - return {
134   - /**
135   - * 工厂对象,创建不同的对象。
136   - * @returns {{createParameterObj, createBcObj}}
137   - */
138   - getFactory: function() {
139   - return _factory;
140   - },
141   -
142   - /**
143   - * 使用发车间隔策略生成时刻表。
144   - * @param paramObj 参数对象
145   - * @param lpArray 路牌数组
146   - * @constructor
147   - */
148   - BXPplaceClassesTime03 : function(paramObj, lpArray) {
149   - // 参数对象
150   - _paramObj = paramObj;
151   -
152   - // 1、初始化行车计划
153   - var schedule = new InternalScheduleObj(_paramObj, lpArray, _factory);
154   - schedule.fnInitDataWithBxLayout();
155   - // 2、将连班路牌的班次补足
156   - schedule.fnCalcuLpBx_lb();
157   -
158   - // 3、修正针对初始化时生成的高峰班次,之前不足的补上,多余的删除
159   - schedule.fnAdjustGfbc(true, true); // 修正上行早高峰
160   - schedule.fnAdjustGfbc(true, false); // 修正下行早高峰
161   - schedule.fnAdjustGfbc(false, true); // 修正上行晚高峰
162   - schedule.fnAdjustGfbc(false, false); // 修正下行晚高峰
163   -
164   - // 4、按照车辆投入运营要求补充班次
165   - schedule.fnCalcuLpBc_yy();
166   -
167   - // 5、根据班型补充所有的不足班次
168   - schedule.fnCalcuLpBx_5_2();
169   - schedule.fnCalcuLpBx_other();
170   -
171   - // 6、补吃饭班次
172   - schedule.fnCalcuEatBc();
173   -
174   - // 7、祛除有删除标记的班次
175   - schedule.fnRemoveDelFlagBc();
176   -
177   - // 8、调整纵向班次间隔
178   - schedule.fnAdjust_vertical_bc_interval();
179   - // TODO:横向调整
180   -
181   - // 9、确定末班车
182   - schedule.fnCalcuLastBc();
183   -
184   - // 10、补进出场例保班次
185   - schedule.fnCalcuOtherBc();
186   -
187   - //-------------------- 输出ganut图上的班次,班型描述 ----------------------//
188   - var gBcData = schedule.fnToGanttBcArray();
189   - // TODO:班型再议
190   - return {'json':gBcData,'bxrcgs':null};
191   -
192   - }
193   -
194   - };
195   -
  1 +/**
  2 + * 主类。
  3 + */
  4 +var Main_v2 = function() {
  5 +
  6 + // 内部工厂类
  7 + var _factoryFun = function() {
  8 + return {
  9 + // 创建参数
  10 + createParameterObj: function(formMap, dataMap) {
  11 + var paramObj = ParameterObj();
  12 + paramObj.wrap(formMap, dataMap);
  13 + return paramObj;
  14 + },
  15 + // 创建班次对象
  16 + createBcObj: function(lpObj, bcType, isUp, fcno, fcTimeObj, paramObj) {
  17 + var _bclc = paramObj.calcuTravelLcNumber(isUp, bcType);
  18 + var _fcsj = fcTimeObj;
  19 + var _bcsj = paramObj.calcuTravelTime(_fcsj, isUp);
  20 + var _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  21 + var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
  22 + var _tccid = paramObj.getTTinfoId();
  23 + var _ttinfoid = paramObj.getTTinfoId();
  24 + var _xl = paramObj.getXlId();
  25 + var _qdz = isUp ? paramObj.getUpQdzObj().id : paramObj.getDownQdzObj().id;
  26 + var _zdz = isUp ? paramObj.getUpZdzObj().id : paramObj.getDownZdzObj().id;
  27 +
  28 + if (bcType == "bd") { // 早例保,传过来的发车时间是第一个班次的发车时间
  29 + if (isUp) { // 上行
  30 + _fcsj = paramObj.addMinute(
  31 + _fcsj,
  32 + -(paramObj.getUpOutTime() + paramObj.getLbTime()));
  33 + _bcsj = paramObj.getLbTime();
  34 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  35 + _stoptime = 0;
  36 + } else { // 下行
  37 + _fcsj = paramObj.addMinute(
  38 + _fcsj,
  39 + -(paramObj.getDownOutTime() + paramObj.getLbTime()));
  40 + _bcsj = paramObj.getLbTime();
  41 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  42 + _stoptime = 0;
  43 + }
  44 + } else if (bcType == "lc") { // 晚例保,传过来的发车时间是最后一个班次的到达时间
  45 + if (isUp) { // 上行
  46 + _fcsj = paramObj.addMinute(
  47 + _fcsj,
  48 + paramObj.getUpInTime());
  49 + _bcsj = paramObj.getLbTime();
  50 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  51 + _stoptime = 0;
  52 + } else { // 下行
  53 + _fcsj = paramObj.addMinute(
  54 + _fcsj,
  55 + paramObj.getDownInTime());
  56 + _bcsj = paramObj.getLbTime();
  57 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  58 + _stoptime = 0;
  59 + }
  60 + } else if (bcType == "out") { // 出场,传过来的发车时间是第一个班次的发车时间
  61 + if (isUp) { // 上行
  62 + _fcsj = paramObj.addMinute(
  63 + _fcsj,
  64 + -paramObj.getUpOutTime());
  65 + _bcsj = paramObj.getUpOutTime();
  66 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  67 + _stoptime = 0;
  68 + } else { // 下行
  69 + _fcsj = paramObj.addMinute(
  70 + _fcsj,
  71 + -paramObj.getDownOutTime());
  72 + _bcsj = paramObj.getDownOutTime();
  73 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  74 + _stoptime = 0;
  75 + }
  76 + } else if (bcType == "in") { // 进场,传过来的发车时间是最后一个班次的到达时间
  77 + if (isUp) { // 上行
  78 + _bcsj = paramObj.getUpInTime();
  79 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  80 + _stoptime = 0;
  81 + } else { // 下行
  82 + _bcsj = paramObj.getDownInTime();
  83 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  84 + _stoptime = 0;
  85 + }
  86 + } else if (bcType == "cf") { // 吃饭班次
  87 + // 以13:00为分界,之前的为午饭,之后的为晚饭
  88 + if (fcTimeObj.isBefore(paramObj.toTimeObj("13:00"))) {
  89 + _bcsj = paramObj.fnGetLunchTime();
  90 + } else {
  91 + _bcsj = paramObj.fnGetDinnerTime();
  92 + }
  93 + _arrsj = paramObj.addMinute(_fcsj, _bcsj);
  94 + _stoptime = 0;
  95 + }
  96 +
  97 + var bcParamObj = {};
  98 + bcParamObj.bcType = bcType; // 班次类型(normal,in_,out, bd, lc, cf等)
  99 + bcParamObj.isUp = isUp; // boolean是否上下行
  100 + bcParamObj.fcno = fcno; // 发车顺序号
  101 + bcParamObj.fcTimeObj = _fcsj; // 发车时间对象
  102 + bcParamObj.bclc = _bclc; // 班次里程
  103 + bcParamObj.bcsj = _bcsj; // 班次历时
  104 + bcParamObj.arrtime = _arrsj; // 到达时间对象
  105 + bcParamObj.stoptime = _stoptime; // 停站时间
  106 + bcParamObj.tccid = _tccid; // 停车场id
  107 + bcParamObj.ttinfoid = _ttinfoid; // 时刻表id
  108 + bcParamObj.xl = _xl; // 线路id
  109 + bcParamObj.qdzid = _qdz; // 起点站id
  110 + bcParamObj.zdzid = _zdz; // 终点站id
  111 +
  112 + return new InternalBcObj(lpObj, bcParamObj);
  113 + }
  114 + };
  115 + };
  116 + var _factory = _factoryFun();
  117 +
  118 + // 所有的时间使用moment.js计算
  119 +
  120 + var _paramObj; // 参数对象
  121 +
  122 + var _bxDesc = [ // 班型描述
  123 + {'type':'六工一休','hoursV':6.66, 'minueV':'6:40', 'qcount': 0, 'avertime': 0},
  124 + {'type':'五工一休','hoursV':6.85, 'minueV':'6:51', 'qcount': 0, 'avertime': 0},
  125 + {'type':'四工一休','hoursV':7.14, 'minueV':'7:08', 'qcount': 0, 'avertime': 0},
  126 + {'type':'三工一休','hoursV':7.61, 'minueV':'7:37', 'qcount': 0, 'avertime': 0},
  127 + {'type':'二工一休','hoursV':8.57, 'minueV':'8:34', 'qcount': 0, 'avertime': 0},
  128 + {'type':'一工一休','hoursV':11.42, 'minueV':'11:25', 'qcount': 0, 'avertime': 0},
  129 + {'type':'五工二休','hoursV':7.99, 'minueV':'8:00', 'qcount': 0, 'avertime': 0},
  130 + {'type':'无工休', 'hoursV':5.43, 'minueV':'5:43', 'qcount': 0, 'avertime': 0}
  131 + ];
  132 +
  133 + return {
  134 + /**
  135 + * 工厂对象,创建不同的对象。
  136 + * @returns {{createParameterObj, createBcObj}}
  137 + */
  138 + getFactory: function() {
  139 + return _factory;
  140 + },
  141 +
  142 + /**
  143 + * 使用发车间隔策略生成时刻表。
  144 + * @param paramObj 参数对象
  145 + * @param lpArray 路牌数组
  146 + * @constructor
  147 + */
  148 + BXPplaceClassesTime03 : function(paramObj, lpArray) {
  149 + // 参数对象
  150 + _paramObj = paramObj;
  151 +
  152 + // 1、初始化行车计划
  153 + var schedule = new InternalScheduleObj(_paramObj, lpArray, _factory);
  154 + schedule.fnInitDataWithBxLayout();
  155 + // 2、将连班路牌的班次补足
  156 + schedule.fnCalcuLpBx_lb();
  157 +
  158 + // 3、修正针对初始化时生成的高峰班次,之前不足的补上,多余的删除
  159 + schedule.fnAdjustGfbc(true, true); // 修正上行早高峰
  160 + schedule.fnAdjustGfbc(true, false); // 修正下行早高峰
  161 + schedule.fnAdjustGfbc(false, true); // 修正上行晚高峰
  162 + schedule.fnAdjustGfbc(false, false); // 修正下行晚高峰
  163 +
  164 + // 4、按照车辆投入运营要求补充班次
  165 + schedule.fnCalcuLpBc_yy();
  166 +
  167 + // 5、根据班型补充所有的不足班次
  168 + schedule.fnCalcuLpBx_5_2();
  169 + schedule.fnCalcuLpBx_other();
  170 +
  171 + // 6、补吃饭班次
  172 + schedule.fnCalcuEatBc();
  173 +
  174 + // 7、祛除有删除标记的班次
  175 + schedule.fnRemoveDelFlagBc();
  176 +
  177 + // 8、调整纵向班次间隔
  178 + schedule.fnAdjust_vertical_bc_interval();
  179 + // TODO:横向调整
  180 +
  181 + // 9、确定末班车
  182 + schedule.fnCalcuLastBc();
  183 +
  184 + // 10、补进出场例保班次
  185 + schedule.fnCalcuOtherBc();
  186 +
  187 + //-------------------- 输出ganut图上的班次,班型描述 ----------------------//
  188 + var gBcData = schedule.fnToGanttBcArray();
  189 + // TODO:班型再议
  190 + return {'json':gBcData,'bxrcgs':null};
  191 +
  192 + }
  193 +
  194 + };
  195 +
196 196 }();
197 197 \ No newline at end of file
... ...
src/main/resources/static/pages/base/timesmodel/js/v3/core/timetable_bc_obj.js
1   -/**
2   - * 时刻表内部班次对象。
3   - * @param iLpIndex 路牌索引
4   - * @param iGroupIndex 圈索引
5   - * @param oParam 其他参数对象
6   - * @constructor
7   - */
8   -var TimeTableBc = function(
9   - iLpIndex,
10   - iGroupIndex,
11   - oParam
12   -) {
13   - // 简单验证
14   - if (isNaN(iLpIndex)) {
15   - throw "new TimeTableBc 路牌索引" + iLpIndex + " 不是int";
16   - }
17   - if (isNaN(iGroupIndex)) {
18   - throw "new TimeTableBc 圈索引" + iGroupIndex + " 不是int";
19   - }
20   - if (typeof oParam == "undefined") {
21   - throw "new TimeTableBc 其他参数对象" + oParam + " 未定义";
22   - }
23   -
24   - /** 路牌索引 */
25   - this._$_iLpIndex = iLpIndex;
26   - /** 圈索引 */
27   - this._$_iGroupIndex = iGroupIndex;
28   -
29   - // 其他参数对象关联的内部参数
30   -
31   - /** 班次类型(normal,in,out等) */
32   - this._$_sBcType = otherParamObj.bcType;
33   - /** 是否上下行 */
34   - this._$_bIsUp = otherParamObj.isUp;
35   - /** 发车顺序号 */
36   - this._$_iFcno = otherParamObj.fcno;
37   - /** 发车时间对象 */
38   - this._$_oFcsjObj = moment(otherParamObj.fcTimeObj);
39   - /** 班次里程 */
40   - this._$_flBclc = otherParamObj.bclc;
41   - /** 班次历时 */
42   - this._$_iBcsj = otherParamObj.bcsj;
43   - /** 到达时间对象 */
44   - this._$_oArrtime = otherParamObj.arrtime;
45   - /** 停站时间 */
46   - this._$_iStoptime = otherParamObj.stoptime;
47   - /** 停车场id */
48   - this._$_iTccid = otherParamObj.tccid;
49   - /** 时刻表id */
50   - this._$_iTtinfoid = otherParamObj.ttinfoid;
51   - /** 线路id */
52   - this._$_iXlid = otherParamObj.xl;
53   - /** 起点站id */
54   - this._$_iQdzid = otherParamObj.qdzid;
55   - /** 终点站id */
56   - this._$_iZdzid = otherParamObj.zdzid;
57   -
58   -};
59   -
  1 +/**
  2 + * 时刻表内部班次对象。
  3 + * @param iLpIndex 路牌索引
  4 + * @param iGroupIndex 圈索引
  5 + * @param oParam 其他参数对象
  6 + * @constructor
  7 + */
  8 +var TimeTableBc = function(
  9 + iLpIndex,
  10 + iGroupIndex,
  11 + oParam
  12 +) {
  13 + // 简单验证
  14 + if (isNaN(iLpIndex)) {
  15 + throw "new TimeTableBc 路牌索引" + iLpIndex + " 不是int";
  16 + }
  17 + if (isNaN(iGroupIndex)) {
  18 + throw "new TimeTableBc 圈索引" + iGroupIndex + " 不是int";
  19 + }
  20 + if (typeof oParam == "undefined") {
  21 + throw "new TimeTableBc 其他参数对象" + oParam + " 未定义";
  22 + }
  23 +
  24 + /** 路牌索引 */
  25 + this._$_iLpIndex = iLpIndex;
  26 + /** 圈索引 */
  27 + this._$_iGroupIndex = iGroupIndex;
  28 +
  29 + // 其他参数对象关联的内部参数
  30 +
  31 + /** 班次类型(normal,in,out等) */
  32 + this._$_sBcType = otherParamObj.bcType;
  33 + /** 是否上下行 */
  34 + this._$_bIsUp = otherParamObj.isUp;
  35 + /** 发车顺序号 */
  36 + this._$_iFcno = otherParamObj.fcno;
  37 + /** 发车时间对象 */
  38 + this._$_oFcsjObj = moment(otherParamObj.fcTimeObj);
  39 + /** 班次里程 */
  40 + this._$_flBclc = otherParamObj.bclc;
  41 + /** 班次历时 */
  42 + this._$_iBcsj = otherParamObj.bcsj;
  43 + /** 到达时间对象 */
  44 + this._$_oArrtime = otherParamObj.arrtime;
  45 + /** 停站时间 */
  46 + this._$_iStoptime = otherParamObj.stoptime;
  47 + /** 停车场id */
  48 + this._$_iTccid = otherParamObj.tccid;
  49 + /** 时刻表id */
  50 + this._$_iTtinfoid = otherParamObj.ttinfoid;
  51 + /** 线路id */
  52 + this._$_iXlid = otherParamObj.xl;
  53 + /** 起点站id */
  54 + this._$_iQdzid = otherParamObj.qdzid;
  55 + /** 终点站id */
  56 + this._$_iZdzid = otherParamObj.zdzid;
  57 +
  58 +};
  59 +
60 60 // TODO
61 61 \ No newline at end of file
... ...
src/main/resources/static/pages/base/timesmodel/js/v3/core/timetable_group_obj.js
1   -
2   -// TODO
3   -var TimeTableGroup = function() {
4   -
5   - /** 一圈几个班次(2个) */
6   - this._$_iUnitBcCount = 2;
7   - /** 是否上行(指圈的第一个班次是否上行) */
8   - this._$_bIsUp;
9   -
10   - /** 圈组的开始时间(初始化一般由上标线确定,如:06:00,开始时间计算时是闭区间) */
11   - this._$_oUnitGroupStartTime;
12   - /** 圈组的结束时间(初始化一般由上标线确定,如:08:41,结束时间计算时是开区间) */
13   - this._$_oUnitGroupEndTime;
14   -
15   - /** 圈组里圈班次可能的总数目(初始化确定,有几个路牌,一个圈组就有几圈-纵向看) */
16   - this._$_iAllUnitCount;
17   - /** 圈组里所有可能班次数组(二维数组,行一班表示有几个路牌,列就表示一圈2个班次) */
18   - this._$_aAllUnitBces = new Array(this._$_iAllUnitBcCount, this._$_iUnitBcCount);
19   -
20   - /** 圈组里每圈之间的发车间隔值数组(第一个间隔为0,上下行一样) */
21   - this._$_aUnitIntervalTime = new Array(this._$_iAllUnitCount);
22   -
23   - // TODO
24   -};
25   -
  1 +
  2 +// TODO
  3 +var TimeTableGroup = function() {
  4 +
  5 + /** 一圈几个班次(2个) */
  6 + this._$_iUnitBcCount = 2;
  7 + /** 是否上行(指圈的第一个班次是否上行) */
  8 + this._$_bIsUp;
  9 +
  10 + /** 圈组的开始时间(初始化一般由上标线确定,如:06:00,开始时间计算时是闭区间) */
  11 + this._$_oUnitGroupStartTime;
  12 + /** 圈组的结束时间(初始化一般由上标线确定,如:08:41,结束时间计算时是开区间) */
  13 + this._$_oUnitGroupEndTime;
  14 +
  15 + /** 圈组里圈班次可能的总数目(初始化确定,有几个路牌,一个圈组就有几圈-纵向看) */
  16 + this._$_iAllUnitCount;
  17 + /** 圈组里所有可能班次数组(二维数组,行一班表示有几个路牌,列就表示一圈2个班次) */
  18 + this._$_aAllUnitBces = new Array(this._$_iAllUnitBcCount, this._$_iUnitBcCount);
  19 +
  20 + /** 圈组里每圈之间的发车间隔值数组(第一个间隔为0,上下行一样) */
  21 + this._$_aUnitIntervalTime = new Array(this._$_iAllUnitCount);
  22 +
  23 + // TODO
  24 +};
  25 +
26 26 // TODO
27 27 \ No newline at end of file
... ...
src/main/resources/static/pages/base/timesmodel/js/v3/core/timetable_lp_obj.js
1   -
2   -
3   -// TODO
4   -var TimeTableLp = function() {
5   -
6   - /** 班次可能的总数目(初始化确定) */
7   - this._$_iAllBcCount;
8   - /** 所有可能班次数组 */
9   - this._$_aAllBces = new Array(this._$_iAllBcCount);
10   -
11   - /** 车次链的个数 */
12   - this._$_iBcChainCount;
13   - /** 车次链数组(每个车次链又是一个数组) */
14   - this._$_aBcChaines;
15   -
16   - // TODO
17   -};
18   -
  1 +
  2 +
  3 +// TODO
  4 +var TimeTableLp = function() {
  5 +
  6 + /** 班次可能的总数目(初始化确定) */
  7 + this._$_iAllBcCount;
  8 + /** 所有可能班次数组 */
  9 + this._$_aAllBces = new Array(this._$_iAllBcCount);
  10 +
  11 + /** 车次链的个数 */
  12 + this._$_iBcChainCount;
  13 + /** 车次链数组(每个车次链又是一个数组) */
  14 + this._$_aBcChaines;
  15 +
  16 + // TODO
  17 +};
  18 +
19 19 // TODO
20 20 \ No newline at end of file
... ...
src/main/resources/static/pages/forms/statement/commandState.html
... ... @@ -41,8 +41,8 @@
41 41 <select class="form-control" name="line" id="line" style="width: 180px;"></select>
42 42 </div>
43 43  
44   - <div style="display: inline-block;margin-left: 15px;">
45   - <span class="item-label" style="width: 80px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;时间: </span>
  44 + <div style="display: inline-block;margin-left: 36px;">
  45 + <span class="item-label" style="width: 80px;">时间: </span>
46 46 <input class="form-control" type="text" id="date" style="width: 180px;"/>
47 47 </div>
48 48 <div style="display:none;margin-left: 8px">
... ...
src/main/resources/static/pages/oil/list_ph.html
... ... @@ -173,7 +173,7 @@
173 173 <thead>
174 174 <tr role="row" class="heading">
175 175 <td width="40px">
176   - <input type="checkbox" id="selectAll" class="group-checkable icheck" >
  176 + <input type="checkbox" id="selectAll" class="group-checkable" >
177 177 </td>
178 178 <td width="40px">序号</td>
179 179 <td width="8%">日期</td>
... ... @@ -327,6 +327,7 @@ onkeyup=&quot;this.value=this.value.replace(/[^(\d||/.)]/g,&#39;&#39;).replace(&#39;.&#39;,&#39;$#$&#39;).rep
327 327 layer.msg('请选择日期.');
328 328 }
329 329 })
  330 +
330 331 //进场等于出场
331 332 $("#outAndIn").on('click', function () {
332 333 // console.log("进场油量等于出场油量");
... ... @@ -970,11 +971,11 @@ onkeyup=&quot;this.value=this.value.replace(/[^(\d||/.)]/g,&#39;&#39;).replace(&#39;.&#39;,&#39;$#$&#39;).rep
970 971 //全选 全不选
971 972 $("#selectAll").on("click", function () {
972 973 if ($(this).is(":checked")) {
973   -// $("[name=id]:checkbox").prop("checked", true);
974   - $("input[name='id']").attr('checked', true)
  974 + $("[name=id]:checkbox").prop("checked", true);
  975 +// $("input[name='id']").attr('checked', true)
975 976 } else {
976   -// $("[name=id]:checkbox").prop("checked", false);
977   - $("input[name='id']").attr('checked', false);
  977 + $("[name=id]:checkbox").prop("checked", false);
  978 +// $("input[name='id']").attr('checked', false);
978 979 }
979 980 });
980 981  
... ...
src/main/resources/static/pages/summary/destory_sch_detail/list.html
... ... @@ -246,7 +246,7 @@
246 246 //开始结束时间
247 247 data.rq_ge = data.rq.substr(0, 10);
248 248 data.rq_le = data.rq.substr(13);
249   - data.order='t';
  249 + //data.order='t';
250 250 delete data.rq;
251 251  
252 252 $.get('/summary/destroy_detail/all', data, function (rs) {
... ...
src/main/resources/static/real_control_v2/fragments/north/nav/history_sch/editor.html
... ... @@ -89,7 +89,7 @@
89 89 <label class="uk-form-label" >售票员</label>
90 90 <div class="uk-form-controls">
91 91 <div class="uk-autocomplete uk-form spy-autocom">
92   - <input type="text" value="{{sch.sGh}}/{{sch.sName}}" name="spy">
  92 + <input type="text" name="spy" value="{{sch.sGh}}/{{sch.sName}}" name="spy">
93 93 </div>
94 94 </div>
95 95 </div>
... ... @@ -268,7 +268,7 @@
268 268 data.jName = data.jsy.split('/')[1];
269 269 delete data.jsy;
270 270 //拆分售票员工号和姓名
271   - if(data.sGh != null){
  271 + if(data.spy != null){
272 272 data.sGh = data.spy.split('/')[0];
273 273 data.sName = data.spy.split('/')[1];
274 274 delete data.spy;
... ...
src/main/resources/static/real_control_v2/js/data/json/north_toolbar.json
... ... @@ -116,6 +116,12 @@
116 116 "text": "换人换车情况统计表",
117 117 "event": "form_changetochange",
118 118 "icon": "uk-icon-table"
  119 + },
  120 + {
  121 + "id": 2.6,
  122 + "text": "班次车辆人员日统计",
  123 + "event": "form_shifday",
  124 + "icon": "uk-icon-table"
119 125 }
120 126 ]
121 127 },
... ...
src/main/resources/static/real_control_v2/js/main.js
... ... @@ -47,7 +47,7 @@ var gb_main_ep = new EventProxy(),
47 47 $('li.map-panel', '#main-tab-content').load('/real_control_v2/mapmonitor/real.html');
48 48 }, 1000);
49 49 //弹出更新说明
50   - //showUpdateDescription();
  50 + showUpdateDescription();
51 51 });
52 52  
53 53 function g_emit(id) {
... ... @@ -168,8 +168,8 @@ var disabled_submit_btn = function (form) {
168 168 function showUpdateDescription() {
169 169 //更新说明
170 170 var updateDescription = {
171   - date: '2017-11-08',
172   - text: '<h5>1、现在点击驾驶员请求信使,也可以定位到班次。</h5><h5>2、修复进场班次不会自动误点待发调整的问题。</h5><h5>3、“指令下发记录” 和 “设备上报记录” 加入线路筛选。</h5><h5>4、尝试修复“自动执行的班车线路”和营运线路套跑时,线路切换指令会延迟触发的问题。</h5>'
  171 + date: '2017-11-23',
  172 + text: '<h5>1、蒽... 更新了一些东西,,, 明天再写更新说明。</h5>'
173 173 };
174 174  
175 175 var storage = window.localStorage
... ...
src/main/resources/static/real_control_v2/js/north/toolbar.js
... ... @@ -226,6 +226,9 @@ var gb_northToolbar = (function () {
226 226 },
227 227 sch_edit_info: function () {
228 228 open_modal('/real_control_v2/fragments/north/nav/sch_edit_info/list.html', {}, modal_opts);
  229 + },
  230 + form_shifday: function () {
  231 + gb_embed_form_hanlde.open_modal_form_fragment('/pages/mforms/shifdays/shifday.html', '班次车辆人员日统计');
229 232 }
230 233 };
231 234  
... ...
src/main/resources/static/real_control_v2/js/utils/svg_data_convert_bf.js
1   -var gb_svg_data_convert = (function () {
2   -
3   - /**
4   - * 合并上下行路由
5   - * type 0 上行 1 下行 2 同名合并 3 异名合并
6   - *
7   - * enableAttr: 是否启用配置信息
8   - */
9   - function mergeRoute(routes, enableAttr, lineCode, loopLine) {
10   - console.log('routesroutes', routes);
11   - //按上下行拆分
12   - routes = gb_common.groupBy(routes, 'directions');
13   - var up = routes[0],
14   - down = routes[1];
15   - //排序
16   - up.sort(upSort);
17   - down.sort(downSort);
18   - var data = [];
19   -
20   - //根据配置处理一下数据
21   - if (enableAttr) {
22   - var svgAttr = gb_data_basic.getSvgAttr(lineCode);
23   - if (svgAttr) {
24   - up = filterByAttrs(svgAttr, up);
25   - down = filterByAttrs(svgAttr, down);
26   - }
27   - }
28   -
29   - //环线 只画上行
30   - if(loopLine){
31   - for (var j = 0; j < up.length; j++) {
32   - var upS = nvl_get(up, j);
33   - op = {
34   - name: [upS.stationName],
35   - id: [get_station_code(upS)],
36   - type: 0,
37   - stationMark: upS.stationMark
38   - };
39   - data.push(op);
40   - }
41   -
42   - //上下行GPS容器
43   - $.each(data, function () {
44   - this.gpsUps = [];
45   - this.gpsDowns = [];
46   - });
47   -
48   - return data;
49   - }
50   -
51   -
52   - //同名站点合并
53   - for (var j = 0; j < up.length; j++) {
54   - var upS = nvl_get(up, j),
55   - downS = nvl_get(down, j),
56   - op = {
57   - name: [upS.stationName],
58   - id: [get_station_code(upS), get_station_code(downS)],
59   - type: 2,
60   - stationMark: upS.stationMark//站点标记
61   - };
62   -
63   - if (upS.stationName != downS.stationName) {
64   - //下行站点在上行路由中是否存在
65   - var dIndex = station_indexof(down, upS, j);
66   - //上行站点在下行路由中是否存在
67   - var uIndex = station_indexof(up, downS, j);
68   - if (dIndex == -1 || dIndex - j > 4) {
69   - if (uIndex == -1 && dIndex - j < 4) {
70   - op.type = 3;
71   - op.name = [upS.stationName, downS.stationName];
72   - }
73   - else {
74   - op.type = 0;
75   - op.id = [get_station_code(upS), -1];
76   - //占位
77   - down.splice(j, 0, {});
78   - }
79   - } else {
80   - for (var t = j; t < dIndex - 1; t++) {
81   - var temp = down[t];
82   - data.push({
83   - name: [temp.stationName],
84   - type: 1,
85   - id: [get_station_code(temp)]
86   - });
87   - }
88   - //delete
89   - down.splice(j, dIndex - 1 - j);
90   - j--;
91   - continue;
92   - }
93   - }
94   - data.push(op);
95   - }
96   -
97   - //将上下行挨着的异名站点合并
98   - var len = data.length - 1,
99   - first, sec;
100   - for (var s = 0; s < len; s++) {
101   - first = data[s];
102   - sec = data[s + 1];
103   -
104   - if (first.type == 0 &&
105   - sec.type == 1) {
106   - data.splice(s, 2, {
107   - name: [first['name'][0], sec['name'][0]],
108   - type: 3,
109   - id: [first['id'][0], sec['id'][0]]
110   - });
111   - len--;
112   - } else if (first.type == 1 && sec.type == 0) {
113   - data.splice(s, 2, {
114   - name: [first['name'][0], sec['name'][0]],
115   - type: 3,
116   - id: [first['id'][0], sec['id'][0]]
117   - });
118   - len--;
119   - }
120   - }
121   -
122   - //上下行GPS容器
123   - $.each(data, function () {
124   - this.gpsUps = [];
125   - this.gpsDowns = [];
126   - });
127   - return data;
128   - };
129   -
130   - var filterByAttrs = function (svgAttr, routes) {
131   - var hideStations = svgAttr.hideStations ? svgAttr.hideStations : [];
132   - var nicknames = svgAttr.nicknames ? svgAttr.nicknames : {};
133   - var stationCode;
134   - $.each(routes, function (i) {
135   - stationCode = this.stationCode
136   - //要隐藏的站点
137   - $.each(hideStations, function (j, hide) {
138   - if (stationCode == hide)
139   - delete routes[i];
140   - });
141   -
142   - //要重命名的站点
143   - if (nicknames[this.stationName]) {
144   - this.stationName = nicknames[this.stationName];
145   - }
146   - });
147   -
148   - var newRoutes = [];
149   - $.each(routes, function (i, station) {
150   - if(station)
151   - newRoutes.push(station);
152   - });
153   -
154   - return newRoutes;
155   - };
156   -
157   - var upSort = function (a, b) {
158   - return a.stationRouteCode - b.stationRouteCode;
159   - };
160   -
161   - var downSort = function (a, b) {
162   - return b.stationRouteCode - a.stationRouteCode;
163   - };
164   -
165   - var station_indexof = function (array, station, start) {
166   - var res = -1;
167   - for (var i = start, obj; obj = array[i++];) {
168   - if (obj.stationName == station.stationName) {
169   - res = i;
170   - break;
171   - }
172   - }
173   - return res;
174   - };
175   -
176   - var get_station_code = function (station) {
177   - return station.stationCode + '_' + station.directions;
178   - };
179   -
180   - var nvl_get = function (list, index) {
181   - return list[index] == null ? {} : list[index];
182   - };
183   -
184   - var groupByStationAndUpdown = function (data) {
185   - //gb_common.groupBy(data, 'stopNo')
186   - var rs = {},
187   - key;
188   - $.each(data, function () {
189   - key = this['stopNo'] + '_' + this['upDown'];
190   - if (!rs[key])
191   - rs[key] = [];
192   -
193   - rs[key].push(this);
194   - });
195   -
196   - return rs;
197   - };
198   - return {mergeRoute: mergeRoute, groupByStationAndUpdown: groupByStationAndUpdown};
199   -})();
  1 +var gb_svg_data_convert = (function () {
  2 +
  3 + /**
  4 + * 合并上下行路由
  5 + * type 0 上行 1 下行 2 同名合并 3 异名合并
  6 + *
  7 + * enableAttr: 是否启用配置信息
  8 + */
  9 + function mergeRoute(routes, enableAttr, lineCode, loopLine) {
  10 + console.log('routesroutes', routes);
  11 + //按上下行拆分
  12 + routes = gb_common.groupBy(routes, 'directions');
  13 + var up = routes[0],
  14 + down = routes[1];
  15 + //排序
  16 + up.sort(upSort);
  17 + down.sort(downSort);
  18 + var data = [];
  19 +
  20 + //根据配置处理一下数据
  21 + if (enableAttr) {
  22 + var svgAttr = gb_data_basic.getSvgAttr(lineCode);
  23 + if (svgAttr) {
  24 + up = filterByAttrs(svgAttr, up);
  25 + down = filterByAttrs(svgAttr, down);
  26 + }
  27 + }
  28 +
  29 + //环线 只画上行
  30 + if(loopLine){
  31 + for (var j = 0; j < up.length; j++) {
  32 + var upS = nvl_get(up, j);
  33 + op = {
  34 + name: [upS.stationName],
  35 + id: [get_station_code(upS)],
  36 + type: 0,
  37 + stationMark: upS.stationMark
  38 + };
  39 + data.push(op);
  40 + }
  41 +
  42 + //上下行GPS容器
  43 + $.each(data, function () {
  44 + this.gpsUps = [];
  45 + this.gpsDowns = [];
  46 + });
  47 +
  48 + return data;
  49 + }
  50 +
  51 +
  52 + //同名站点合并
  53 + for (var j = 0; j < up.length; j++) {
  54 + var upS = nvl_get(up, j),
  55 + downS = nvl_get(down, j),
  56 + op = {
  57 + name: [upS.stationName],
  58 + id: [get_station_code(upS), get_station_code(downS)],
  59 + type: 2,
  60 + stationMark: upS.stationMark//站点标记
  61 + };
  62 +
  63 + if (upS.stationName != downS.stationName) {
  64 + //下行站点在上行路由中是否存在
  65 + var dIndex = station_indexof(down, upS, j);
  66 + //上行站点在下行路由中是否存在
  67 + var uIndex = station_indexof(up, downS, j);
  68 + if (dIndex == -1 || dIndex - j > 4) {
  69 + if (uIndex == -1 && dIndex - j < 4) {
  70 + op.type = 3;
  71 + op.name = [upS.stationName, downS.stationName];
  72 + }
  73 + else {
  74 + op.type = 0;
  75 + op.id = [get_station_code(upS), -1];
  76 + //占位
  77 + down.splice(j, 0, {});
  78 + }
  79 + } else {
  80 + for (var t = j; t < dIndex - 1; t++) {
  81 + var temp = down[t];
  82 + data.push({
  83 + name: [temp.stationName],
  84 + type: 1,
  85 + id: [get_station_code(temp)]
  86 + });
  87 + }
  88 + //delete
  89 + down.splice(j, dIndex - 1 - j);
  90 + j--;
  91 + continue;
  92 + }
  93 + }
  94 + data.push(op);
  95 + }
  96 +
  97 + //将上下行挨着的异名站点合并
  98 + var len = data.length - 1,
  99 + first, sec;
  100 + for (var s = 0; s < len; s++) {
  101 + first = data[s];
  102 + sec = data[s + 1];
  103 +
  104 + if (first.type == 0 &&
  105 + sec.type == 1) {
  106 + data.splice(s, 2, {
  107 + name: [first['name'][0], sec['name'][0]],
  108 + type: 3,
  109 + id: [first['id'][0], sec['id'][0]]
  110 + });
  111 + len--;
  112 + } else if (first.type == 1 && sec.type == 0) {
  113 + data.splice(s, 2, {
  114 + name: [first['name'][0], sec['name'][0]],
  115 + type: 3,
  116 + id: [first['id'][0], sec['id'][0]]
  117 + });
  118 + len--;
  119 + }
  120 + }
  121 +
  122 + //上下行GPS容器
  123 + $.each(data, function () {
  124 + this.gpsUps = [];
  125 + this.gpsDowns = [];
  126 + });
  127 + return data;
  128 + };
  129 +
  130 + var filterByAttrs = function (svgAttr, routes) {
  131 + var hideStations = svgAttr.hideStations ? svgAttr.hideStations : [];
  132 + var nicknames = svgAttr.nicknames ? svgAttr.nicknames : {};
  133 + var stationCode;
  134 + $.each(routes, function (i) {
  135 + stationCode = this.stationCode
  136 + //要隐藏的站点
  137 + $.each(hideStations, function (j, hide) {
  138 + if (stationCode == hide)
  139 + delete routes[i];
  140 + });
  141 +
  142 + //要重命名的站点
  143 + if (nicknames[this.stationName]) {
  144 + this.stationName = nicknames[this.stationName];
  145 + }
  146 + });
  147 +
  148 + var newRoutes = [];
  149 + $.each(routes, function (i, station) {
  150 + if(station)
  151 + newRoutes.push(station);
  152 + });
  153 +
  154 + return newRoutes;
  155 + };
  156 +
  157 + var upSort = function (a, b) {
  158 + return a.stationRouteCode - b.stationRouteCode;
  159 + };
  160 +
  161 + var downSort = function (a, b) {
  162 + return b.stationRouteCode - a.stationRouteCode;
  163 + };
  164 +
  165 + var station_indexof = function (array, station, start) {
  166 + var res = -1;
  167 + for (var i = start, obj; obj = array[i++];) {
  168 + if (obj.stationName == station.stationName) {
  169 + res = i;
  170 + break;
  171 + }
  172 + }
  173 + return res;
  174 + };
  175 +
  176 + var get_station_code = function (station) {
  177 + return station.stationCode + '_' + station.directions;
  178 + };
  179 +
  180 + var nvl_get = function (list, index) {
  181 + return list[index] == null ? {} : list[index];
  182 + };
  183 +
  184 + var groupByStationAndUpdown = function (data) {
  185 + //gb_common.groupBy(data, 'stopNo')
  186 + var rs = {},
  187 + key;
  188 + $.each(data, function () {
  189 + key = this['stopNo'] + '_' + this['upDown'];
  190 + if (!rs[key])
  191 + rs[key] = [];
  192 +
  193 + rs[key].push(this);
  194 + });
  195 +
  196 + return rs;
  197 + };
  198 + return {mergeRoute: mergeRoute, groupByStationAndUpdown: groupByStationAndUpdown};
  199 +})();
... ...