Commit 9b2cec0e1fa25f04ff6c64935f90c8eb49783b8e

Authored by 王通
1 parent f125ea9a

1.加入混合自动执行+自动执行偏移的托管以及营运后路单计算功能

src/main/java/com/bsth/XDApplication.java
@@ -151,7 +151,7 @@ public class XDApplication implements CommandLineRunner { @@ -151,7 +151,7 @@ public class XDApplication implements CommandLineRunner {
151 /** 线调业务 */ 151 /** 线调业务 */
152 sexec.scheduleWithFixedDelay(scheduleRefreshThread, 10, 120, TimeUnit.SECONDS);//班次更新线程 152 sexec.scheduleWithFixedDelay(scheduleRefreshThread, 10, 120, TimeUnit.SECONDS);//班次更新线程
153 sexec.scheduleWithFixedDelay(scheduleLateThread, 140, 20, TimeUnit.SECONDS);//检查班次误点 153 sexec.scheduleWithFixedDelay(scheduleLateThread, 140, 20, TimeUnit.SECONDS);//检查班次误点
154 - sexec.scheduleWithFixedDelay(gpsDataLoader, 100, 2, TimeUnit.SECONDS);//抓取GPS数据 154 + sexec.scheduleWithFixedDelay(gpsDataLoader, 0, 2, TimeUnit.SECONDS);//抓取GPS数据
155 //sexec.scheduleWithFixedDelay(rfidDataLoader, 5, 5, TimeUnit.SECONDS);//抓取RFID数据 155 //sexec.scheduleWithFixedDelay(rfidDataLoader, 5, 5, TimeUnit.SECONDS);//抓取RFID数据
156 sexec.scheduleWithFixedDelay(fixedCheckStationCodeThread, 60, 60 * 5, TimeUnit.SECONDS);//检查班次站点编码 156 sexec.scheduleWithFixedDelay(fixedCheckStationCodeThread, 60, 60 * 5, TimeUnit.SECONDS);//检查班次站点编码
157 157
src/main/java/com/bsth/config/SchedulerConfig.java 0 → 100644
  1 +package com.bsth.config;
  2 +
  3 +import org.springframework.beans.BeansException;
  4 +import org.springframework.context.ApplicationContext;
  5 +import org.springframework.context.ApplicationContextAware;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.Configuration;
  8 +import org.springframework.scheduling.annotation.SchedulingConfigurer;
  9 +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
  10 +import org.springframework.scheduling.config.ScheduledTaskRegistrar;
  11 +
  12 +@Configuration
  13 +public class SchedulerConfig implements SchedulingConfigurer, ApplicationContextAware {
  14 +
  15 + private static ApplicationContext context;
  16 +
  17 + private final int POOL_SIZE = 10;
  18 +
  19 + @Override
  20 + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
  21 + ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler) context.getBean("threadPoolTaskScheduler");
  22 + taskRegistrar.setTaskScheduler(scheduler);
  23 + }
  24 +
  25 + @Bean("threadPoolTaskScheduler")
  26 + public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
  27 + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
  28 + threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
  29 + threadPoolTaskScheduler.setThreadNamePrefix("TaskScheduler-");
  30 + threadPoolTaskScheduler.initialize();
  31 +
  32 + return threadPoolTaskScheduler;
  33 + }
  34 +
  35 + @Override
  36 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  37 + context = applicationContext;
  38 + }
  39 +}
src/main/java/com/bsth/data/SystemParamCache.java
@@ -30,7 +30,8 @@ public class SystemParamCache implements InitializingBean { @@ -30,7 +30,8 @@ public class SystemParamCache implements InitializingBean {
30 } 30 }
31 31
32 public static String getUrlHttpGpsReal() { 32 public static String getUrlHttpGpsReal() {
33 - return systemParamService1.getValue(SystemParamKeys.URL_HTTP_GPS_REAL); 33 + return "http://10.10.2.20:8080/transport_server/rtgps/";
  34 + //return systemParamService1.getValue(SystemParamKeys.URL_HTTP_GPS_REAL);
34 } 35 }
35 36
36 public static String getUrlHttpDirective() { 37 public static String getUrlHttpDirective() {
src/main/java/com/bsth/data/gpsdata_v2/handlers/InStationProcess.java
@@ -51,7 +51,7 @@ public class InStationProcess { @@ -51,7 +51,7 @@ public class InStationProcess {
51 public void process(GpsEntity gps) { 51 public void process(GpsEntity gps) {
52 //自动执行的班次信号,滚蛋 52 //自动执行的班次信号,滚蛋
53 LineConfig config = lineConfigData.get(gps.getLineId()); 53 LineConfig config = lineConfigData.get(gps.getLineId());
54 - if (null != config && config.isAutoExec()) 54 + if (null != config && config.isAutoExec() && config.getAutoExecOffset() == 0)
55 return; 55 return;
56 56
57 GpsEntity prev = GpsCacheData.getPrev(gps); 57 GpsEntity prev = GpsCacheData.getPrev(gps);
@@ -139,6 +139,12 @@ public class InStationProcess { @@ -139,6 +139,12 @@ public class InStationProcess {
139 */ 139 */
140 private void inEndStation(ScheduleRealInfo sch, GpsEntity gps) { 140 private void inEndStation(ScheduleRealInfo sch, GpsEntity gps) {
141 String nbbm = sch.getClZbh(); 141 String nbbm = sch.getClZbh();
  142 + LineConfig lineConfig = lineConfigData.get(gps.getLineId());
  143 + if (lineConfig != null && lineConfig.isAutoExec() && lineConfig.getAutoExecOffset() > 0) {
  144 + if (gps.getTimestamp() < sch.getZdsjT() - lineConfig.getAutoExecOffset() * 60000 || gps.getTimestamp() > sch.getZdsjT() + lineConfig.getAutoExecOffset() * 60000) {
  145 + return;
  146 + }
  147 + }
142 //校验进站前置约束 148 //校验进站前置约束
143 if (!validInPremise(gps) && isNormalSch(sch)) 149 if (!validInPremise(gps) && isNormalSch(sch))
144 return; 150 return;
src/main/java/com/bsth/data/gpsdata_v2/handlers/OutStationProcess.java
@@ -46,7 +46,7 @@ public class OutStationProcess { @@ -46,7 +46,7 @@ public class OutStationProcess {
46 public void process(GpsEntity gps) { 46 public void process(GpsEntity gps) {
47 //自动执行的线路,滚蛋 47 //自动执行的线路,滚蛋
48 LineConfig config = lineConfigData.get(gps.getLineId()); 48 LineConfig config = lineConfigData.get(gps.getLineId());
49 - if (null != config && config.isAutoExec()) 49 + if (null != config && config.isAutoExec() && config.getAutoExecOffset() == 0)
50 return; 50 return;
51 51
52 GpsEntity prev = GpsCacheData.getPrev(gps); 52 GpsEntity prev = GpsCacheData.getPrev(gps);
@@ -86,6 +86,13 @@ public class OutStationProcess { @@ -86,6 +86,13 @@ public class OutStationProcess {
86 ((sch.getQdzCode().equals(prev.getStopNo()) 86 ((sch.getQdzCode().equals(prev.getStopNo())
87 && (gps.getInstation() == 0 || !gps.getStopNo().equals(prev.getStopNo()))) 87 && (gps.getInstation() == 0 || !gps.getStopNo().equals(prev.getStopNo())))
88 || sch.getQdzCode().equals(prev.getCarparkNo()))) { 88 || sch.getQdzCode().equals(prev.getCarparkNo()))) {
  89 + LineConfig lineConfig = lineConfigData.get(gps.getLineId());
  90 + if (lineConfig != null && lineConfig.isAutoExec() && lineConfig.getAutoExecOffset() > 0) {
  91 + if (gps.getTimestamp() < sch.getDfsjT() - lineConfig.getAutoExecOffset() * 60000 || gps.getTimestamp() > sch.getDfsjT() + lineConfig.getAutoExecOffset() * 60000) {
  92 + return;
  93 + }
  94 + }
  95 +
89 //发车班次匹配 96 //发车班次匹配
90 if (!signalSchPlanMatcher.outMatch(gps, sch)) { 97 if (!signalSchPlanMatcher.outMatch(gps, sch)) {
91 outStation(gps, prev); 98 outStation(gps, prev);
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 + public static boolean isGpsInSpecialStation(StationRoute sr, Point point) {
  57 + if (sr.getPolygon() == null) {
  58 + if (getDistance(sr.getPoint(), point) < sr.getRadius()) {
  59 + return true;
  60 + }
  61 + } else if(isPointInPolygon(point, sr.getPolygon())){
  62 + return true;
  63 + }
  64 +
  65 + return false;
  66 + }
  67 +
  68 + private static StationRoute findNearStation(List<StationRoute> rs, GpsEntity gps) {
  69 + if(rs.size() > 1){
  70 + //按路由顺序排序
  71 + Collections.sort(rs, sComp);
  72 +
  73 + //上一个进出的站点
  74 + StationRoute ps = GpsCacheData.prevStation(gps);
  75 + if(null != ps){
  76 + for(StationRoute s : rs){
  77 + if(s.getRouteSort() >= ps.getRouteSort())
  78 + return s;
  79 + }
  80 + }
  81 + }
  82 + return rs.get(0);
  83 + }
  84 +
  85 +
  86 + public static double getDistance(Point p1, Point p2) {
  87 + double lng1 = getLoop(p1.getLon(), -180, 180), lat1 = getRange(
  88 + p1.getLat(), -74, 74);
  89 + double lng2 = getLoop(p2.getLon(), -180, 180), lat2 = getRange(
  90 + p2.getLat(), -74, 74);
  91 +
  92 + double x1, x2, y1, y2;
  93 + x1 = degreeToRad(lng1);
  94 + y1 = degreeToRad(lat1);
  95 + x2 = degreeToRad(lng2);
  96 + y2 = degreeToRad(lat2);
  97 + return EARTH_RADIUS
  98 + * Math.acos((Math.sin(y1) * Math.sin(y2) + Math.cos(y1)
  99 + * Math.cos(y2) * Math.cos(x2 - x1)));
  100 + }
  101 +
  102 + private static double getLoop(double v, double a, double b) {
  103 + while (v > b) {
  104 + v -= b - a;
  105 + }
  106 + while (v < a) {
  107 + v += b - a;
  108 + }
  109 + return v;
  110 + }
  111 +
  112 + private static double getRange(double v, double a, double b) {
  113 + v = Math.min(Math.max(v, a), b);
  114 + return v;
  115 + }
  116 +
  117 + private static double degreeToRad(double degree) {
  118 + return Math.PI * degree / 180;
  119 + }
  120 +
  121 + public static double getDistanceFromLine(CtLineString lineString, Point p){
  122 + return getDistanceFromLine(lineString.getS(), lineString.getE(), p);
  123 + }
  124 +
  125 + /**
  126 + * 计算点 到 线的距离
  127 + * @param line
  128 + * @param p
  129 + * @return
  130 + */
  131 + public static double getDistanceFromLine(Point s, Point e, Point p){
  132 + double d1 = getDistance(s, p);
  133 + double d2 = getDistance(p, e);
  134 + double d3 = getDistance(s, e);
  135 + double distance = 0;
  136 +
  137 + double alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3));
  138 + double beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3));
  139 +
  140 + if(alpha>Math.PI/2) {
  141 + distance = d1;
  142 + }
  143 + else if(beta > Math.PI/2) {
  144 + distance = d2;
  145 + }
  146 + else {
  147 + distance = Math.sin(alpha) * d1;
  148 + }
  149 + return distance;
  150 + }
  151 +
  152 + /**
  153 + * gps 是否在某个停车场内
  154 + * @param gps
  155 + * @return
  156 + */
  157 + public static String gpsInCarpark(GpsEntity gps){
  158 + Point point = new Point(gps.getLon(), gps.getLat());
  159 + Map<String, Polygon> carparkMap = GeoCacheData.tccMap;
  160 +
  161 + Set<String> codes = carparkMap.keySet();
  162 + for(String code : codes){
  163 + if(isPointInPolygon(point, carparkMap.get(code))){
  164 + return code;
  165 + }
  166 + }
  167 + return null;
  168 + }
  169 +
  170 + /**
  171 + * 是否在进站前置围栏内
  172 + * @param gps
  173 + * @return
  174 + */
  175 + public static String gpsInPremiseGeo(GpsEntity gps) {
  176 + List<PreconditionGeo> list = GeoCacheData.premiseGeoMap.get(gps.getLineId()+"_"+gps.getUpDown());
  177 +
  178 + if(null == list || list.size()==0)
  179 + return null;
  180 +
  181 + Point point = new Point(gps.getLon(), gps.getLat());
  182 + for(PreconditionGeo p : list){
  183 + if(isPointInPolygon(point, p.getPolygon())){
  184 + return p.getStationCode();
  185 + }
  186 + }
  187 + return null;
  188 + }
  189 +
  190 + /**
  191 + * 是否是有效的连续点
  192 + * @param prevGps
  193 + * @param gps
  194 + * @return
  195 + */
  196 + public static boolean overdue(GpsEntity prevGps, GpsEntity gps) {
  197 + return gps.getTimestamp() - prevGps.getTimestamp() < 120000;
  198 + }
  199 +
  200 + /**
  201 + * 计算2条直线的最短距离
  202 + * @param p1
  203 + * @param p2
  204 + * @param p3
  205 + * @param p4
  206 + * @return
  207 + */
  208 + public static double getDistanceLineToLine(Point p1, Point p2, Point p3, Point p4){
  209 + double distance;
  210 + double x1 = p1.getLat(); //A点坐标(x1,y1,z1)
  211 + double y1 = p1.getLon();
  212 + double z1 = 0;
  213 + double x2 = p2.getLat(); //B点坐标(x2,y2,z2)
  214 + double y2 = p2.getLon();
  215 + double z2 = 0;
  216 + double x3 = p3.getLat(); //C点坐标(x3,y3,z3)
  217 + double y3 = p3.getLon();
  218 + double z3 = 0;
  219 + double x4 = p4.getLat(); //D点坐标(x4,y4,z4)
  220 + double y4 = p4.getLon();
  221 + double z4 = 0;
  222 +
  223 + double a = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1);
  224 + double b = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
  225 + double c = -((x1-x2)*(x1-x3)+(y1-y2)*(y1-y3)+(z1-z2)*(z1-z3));
  226 +
  227 + double d = -((x2-x1)*(x4-x3)+(y2-y1)*(y4-y3)+(z2-z1)*(z4-z3));
  228 + double e = (x4-x3)*(x4-x3)+(y4-y3)*(y4-y3)+(z4-z3)*(z4-z3);
  229 + double f = -((x1-x3)*(x4-x3)+(y1-y3)*(y4-y3)+(z1-z3)*(z4-z3));
  230 +
  231 + //平行
  232 + if ((a*e-b*d)==0&&(b*d-a*e)==0)
  233 + {
  234 + double d1 = getDistance(p1, p3);
  235 + double d2 = getDistance(p1, p4);
  236 + distance = (d1<d2)?d1:d2;
  237 + return distance;
  238 + }
  239 +
  240 + double s = (b*f-e*c)/(a*e-b*d);
  241 + double t = (a*f-d*c)/(b*d-a*e);
  242 +
  243 + //说明P点落在线段AB上,Q点落在线段CD上
  244 + if(0<=s&&s<=1&&0<=t&&t<=1)
  245 + {
  246 + //2条线段的公垂线段PQ;
  247 + //P点坐标
  248 + double X = x1+s*(x2-x1);
  249 + double Y = y1+s*(y2-y1);
  250 + double Z = z1+s*(z2-z1);
  251 + //Q点坐标
  252 + double U = x3+t*(x4-x3);
  253 + double V = y3+t*(y4-y3);
  254 + double W = z3+t*(z4-z3);
  255 +
  256 + Point p = new Point(Y, X);
  257 + Point q = new Point(V, U);
  258 + distance = getDistance(p, q);
  259 + }
  260 + else
  261 + {
  262 + double d1 = getDistanceFromLine(p3,p4,p1);
  263 + double d2 = getDistanceFromLine(p3,p4,p2);
  264 + double d3 = getDistanceFromLine(p1,p2,p3);
  265 + double d4 = getDistanceFromLine(p1,p2,p4);
  266 + distance = (d1<d2)?d1:d2;
  267 + distance = (distance<d3)?distance:d3;
  268 + distance = (distance<d4)?distance:d4;
  269 + }
  270 +
  271 + return distance;
  272 + }
  273 +
  274 + /**
  275 + * 计算点 到 线的垂直交点
  276 + * @param lp1
  277 + * @param lp2
  278 + * @param p
  279 + * @return
  280 + */
  281 + public static Point perpendularPoint(Point lp1, Point lp2, Point p){
  282 + double a = lp1.getLat() - lp2.getLat(), b = lp2.getLon() - lp1.getLon(), c = lp1.getLon() * lp2.getLat() - lp2.getLon() * lp1.getLat();
  283 + double lon = (Math.pow(b, 2) * p.getLon() - a * b * p.getLat() - a * c) / (Math.pow(a, 2) + Math.pow(b, 2));
  284 + double lat = (Math.pow(a, 2) * p.getLat() - a * b * p.getLon() - b * c) / (Math.pow(a, 2) + Math.pow(b, 2));
  285 +
  286 + return new Point(lon, lat);
  287 + }
  288 +
  289 + public static boolean isPointInRect(Point point, Bounds bounds) {
  290 + Point sw = bounds.getSouthWest(); // 西南脚点
  291 + Point ne = bounds.getNorthEast(); // 东北脚点
  292 + return (point.getLon() >= sw.getLon() && point.getLon() <= ne.getLon()
  293 + && point.getLat() >= sw.getLat() && point.getLat() <= ne
  294 + .getLat());
  295 + }
  296 +
  297 + public static boolean isPointInPolygon(Point point, Polygon polygon) {
  298 + Bounds polygonBounds = polygon.getBounds();
  299 + if (!isPointInRect(point, polygonBounds)) {
  300 + return false;
  301 + }
  302 +
  303 + List<Point> pts = polygon.getPoints();// 获取多边形点
  304 +
  305 + // 下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
  306 + // 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
  307 + // 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
  308 +
  309 + int N = pts.size();
  310 + boolean boundOrVertex = true; // 如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
  311 + int intersectCount = 0;// cross points count of x
  312 + double precision = 2e-10; // 浮点类型计算时候与0比较时候的容差
  313 + Point p1, p2;// neighbour bound vertices
  314 + Point p = point; // 测试点
  315 +
  316 + p1 = pts.get(0);// left vertex
  317 + for (int i = 1; i <= N; ++i) {// check all rays
  318 + if (p.equals(p1)) {
  319 + return boundOrVertex;// p is an vertex
  320 + }
  321 +
  322 + p2 = pts.get(i % N);// right vertex
  323 + if (p.getLat() < Math.min(p1.getLat(), p2.getLat())
  324 + || p.getLat() > Math.max(p1.getLat(), p2.getLat())) {// ray
  325 + // is
  326 + // outside
  327 + // of
  328 + // our
  329 + // interests
  330 + p1 = p2;
  331 + continue;// next ray left point
  332 + }
  333 +
  334 + if (p.getLat() > Math.min(p1.getLat(), p2.getLat())
  335 + && p.getLat() < Math.max(p1.getLat(), p2.getLat())) {// ray
  336 + // is
  337 + // crossing
  338 + // over
  339 + // by
  340 + // the
  341 + // algorithm
  342 + // (common
  343 + // part
  344 + // of)
  345 + if (p.getLon() <= Math.max(p1.getLon(), p2.getLon())) {// x is
  346 + // before
  347 + // of
  348 + // ray
  349 + if (p1.getLat() == p2.getLat()
  350 + && p.getLon() >= Math.min(p1.getLon(), p2.getLon())) {// overlies
  351 + // on
  352 + // a
  353 + // horizontal
  354 + // ray
  355 + return boundOrVertex;
  356 + }
  357 +
  358 + if (p1.getLon() == p2.getLon()) {// ray is vertical
  359 + if (p1.getLon() == p.getLon()) {// overlies on a
  360 + // vertical ray
  361 + return boundOrVertex;
  362 + } else {// before ray
  363 + ++intersectCount;
  364 + }
  365 + } else {// cross point on the left side
  366 + double xinters = (p.getLat() - p1.getLat())
  367 + * (p2.getLon() - p1.getLon())
  368 + / (p2.getLat() - p1.getLat()) + p1.getLon();// cross
  369 + // point
  370 + // of
  371 + // lng
  372 + if (Math.abs(p.getLon() - xinters) < precision) {// overlies
  373 + // on
  374 + // a
  375 + // ray
  376 + return boundOrVertex;
  377 + }
  378 +
  379 + if (p.getLon() < xinters) {// before ray
  380 + ++intersectCount;
  381 + }
  382 + }
  383 + }
  384 + } else {// special case when ray is crossing through the vertex
  385 + if (p.getLat() == p2.getLat() && p.getLon() <= p2.getLon()) {// p
  386 + // crossing
  387 + // over
  388 + // p2
  389 + Point p3 = pts.get((i + 1) % N); // next vertex
  390 + if (p.getLat() >= Math.min(p1.getLat(), p3.getLat())
  391 + && p.getLat() <= Math.max(p1.getLat(), p3.getLat())) {// p.lat
  392 + // lies
  393 + // between
  394 + // p1.lat
  395 + // &
  396 + // p3.lat
  397 + ++intersectCount;
  398 + } else {
  399 + intersectCount += 2;
  400 + }
  401 + }
  402 + }
  403 + p1 = p2;// next ray left point
  404 + }
  405 +
  406 + if (intersectCount % 2 == 0) {// 偶数在多边形外
  407 + return false;
  408 + } else { // 奇数在多边形内
  409 + return true;
  410 + }
  411 + }
  412 +
  413 +}
src/main/java/com/bsth/data/schedule/SchAttrCalculator.java
1 -package com.bsth.data.schedule;  
2 -  
3 -import com.bsth.data.LineConfigData;  
4 -import com.bsth.entity.realcontrol.LineConfig;  
5 -import com.bsth.entity.realcontrol.ScheduleRealInfo;  
6 -import org.apache.commons.lang3.StringUtils;  
7 -import org.joda.time.format.DateTimeFormat;  
8 -import org.joda.time.format.DateTimeFormatter;  
9 -import org.slf4j.Logger;  
10 -import org.slf4j.LoggerFactory;  
11 -import org.springframework.beans.factory.annotation.Autowired;  
12 -import org.springframework.stereotype.Component;  
13 -  
14 -import java.text.ParseException;  
15 -import java.util.ArrayList;  
16 -import java.util.Collections;  
17 -import java.util.List;  
18 -  
19 -/**  
20 - * @author PanZhao  
21 - * @ClassName: SchAttrCalculator  
22 - * @Description: TODO(班次相关属性计算器)  
23 - * @date 2016年8月15日 下午4:40:26  
24 - */  
25 -@Component  
26 -public class SchAttrCalculator {  
27 -  
28 - @Autowired  
29 - LineConfigData lineConfigData;  
30 -  
31 - private final static long DAY_TIME = 1000 * 60 * 60 * 24L;  
32 -  
33 - Logger logger = LoggerFactory.getLogger(this.getClass());  
34 -  
35 - private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd"), fmtHHmm = DateTimeFormat.forPattern("HH:mm"), fmtyyyyMMddHHmm = DateTimeFormat.forPattern("yyyy-MM-ddHH:mm");  
36 -  
37 - /**  
38 - * @Title: calcRealDate  
39 - * @Description: TODO(计算班次的真实执行日期)  
40 - */  
41 - public SchAttrCalculator calcRealDate(ScheduleRealInfo sch) {  
42 - LineConfig conf = lineConfigData.get(sch.getXlBm());  
43 -  
44 - try {  
45 - if (null == sch.getFcsjT())  
46 - calcFcsjTime(sch);  
47 -  
48 - String rq = sch.getScheduleDateStr();  
49 - //计发時間  
50 - sch.setFcsjAll(getTime(rq, sch.getFcsj(), conf));  
51 -  
52 - //待发時間  
53 - sch.setDfsjAll(getTime(rq, sch.getDfsj(), conf));  
54 - /*if (sch.getDfsj().compareTo(conf.getStartOpt()) < 0) {  
55 - sch.setDfsjAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getDfsj()) + DAY_TIME);  
56 - } else  
57 - sch.setDfsjAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getDfsj()));*/  
58 -  
59 - //实发時間  
60 - sch.setFcsjActualAll(getTime(rq, sch.getFcsjActual(), conf));  
61 - /*if (StringUtils.isNotEmpty(sch.getFcsjActual()) &&  
62 - sch.getFcsjActual().compareTo(conf.getStartOpt()) < 0) {  
63 - sch.setFcsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getFcsjActual()) + DAY_TIME);  
64 - }*/  
65 -  
66 - //实际终点時間  
67 - sch.setZdsjActualAll(getTime(rq, sch.getZdsjActual(), conf));  
68 - /*if (StringUtils.isNotEmpty(sch.getZdsjActual()) &&  
69 - sch.getZdsjActual().compareTo(conf.getStartOpt()) < 0) {  
70 - sch.setZdsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getZdsjActual()) + DAY_TIME);  
71 - }*/  
72 -  
73 - sch.setRealExecDate(fmtyyyyMMdd.print(sch.getFcsjT()));  
74 - } catch (Exception e) {  
75 - logger.error("", e);  
76 - }  
77 - return this;  
78 - }  
79 -  
80 - public Long getTime(String rq, String timeStr, LineConfig conf) {  
81 - Long t = null;  
82 - if (StringUtils.isNotEmpty(timeStr)) {  
83 - t = fmtyyyyMMddHHmm.parseMillis(rq + timeStr);  
84 - if(timeStr.compareTo(conf.getStartOpt()) < 0)  
85 - return t + DAY_TIME;  
86 - }  
87 - return t;  
88 - }  
89 -  
90 - /**  
91 - * @Title: calcAllTimeByFcsj  
92 - * @Description: TODO(根据发车时间字符串计算 (计发时间,终点时间,待发时间))  
93 - */  
94 - public SchAttrCalculator calcAllTimeByFcsj(ScheduleRealInfo sch) {  
95 - try {  
96 - // 生成时间戳  
97 - calcTimestamp(sch);  
98 -  
99 - // 计划终点时间  
100 - if (sch.getBcsj() != null) {  
101 - sch.setZdsjT(sch.getFcsjT() + (sch.getBcsj() * 60 * 1000));  
102 - sch.setZdsj(fmtHHmm.print(sch.getZdsjT()));  
103 - }  
104 - } catch (ParseException e) {  
105 - logger.error("", e);  
106 - }  
107 - return this;  
108 - }  
109 -  
110 - /**  
111 - * @Title: calcQdzTimePlan  
112 - * @Description: TODO(计算班次的起点应到时间)  
113 - */  
114 - public void calcQdzTimePlan(List<ScheduleRealInfo> list) {  
115 - Collections.sort(list, new ScheduleComparator.FCSJ());  
116 -  
117 - int len = list.size();  
118 - if (len == 0)  
119 - return;  
120 -  
121 - ScheduleRealInfo prve = list.get(0), curr;  
122 - for (int i = 1; i < len; i++) {  
123 - curr = list.get(i);  
124 -  
125 - if (isJoin(prve, curr)) {  
126 - curr.setQdzArrDatejh(prve.getZdsj());  
127 - if (StringUtils.isNotEmpty(prve.getZdsjActual()))  
128 - curr.setQdzArrDatesj(prve.getZdsjActual());  
129 - }  
130 - prve = curr;  
131 - }  
132 - }  
133 -  
134 - private boolean isJoin(ScheduleRealInfo prve, ScheduleRealInfo curr) {  
135 - return prve.getZdzName().equals(curr.getQdzName())//名称相等  
136 - || prve.getZdzCode().equals(curr.getQdzCode())//编码相等  
137 - || prve.getZdzName().startsWith(curr.getQdzName())//起始包括  
138 - || curr.getQdzName().startsWith(prve.getZdzName());//起始包括  
139 - }  
140 -  
141 - /**  
142 - * @Title: updateQdzTimePlan  
143 - * @Description: TODO(更新班次的起点应到时间) 并返回被更新的班次  
144 - */  
145 - public List<ScheduleRealInfo> updateQdzTimePlan(List<ScheduleRealInfo> list) {  
146 - Collections.sort(list, new ScheduleComparator.FCSJ());  
147 -  
148 - List<ScheduleRealInfo> updateList = new ArrayList<>();  
149 - int len = list.size();  
150 - if (len == 0)  
151 - return updateList;  
152 -  
153 - ScheduleRealInfo prve = list.get(0), curr;  
154 - for (int i = 1; i < len; i++) {  
155 - curr = list.get(i);  
156 -  
157 - if (prve.getZdzName().equals(curr.getQdzName())  
158 - || prve.getZdzCode().equals(curr.getQdzCode())) {  
159 -  
160 - if (curr.getQdzArrDatejh() != null && prve.getZdsj().equals(curr.getQdzArrDatejh())) {  
161 - prve = curr;  
162 - continue;  
163 - }  
164 -  
165 - curr.setQdzArrDatejh(prve.getZdsj());  
166 - updateList.add(curr);  
167 - } else {  
168 - curr.setQdzArrDatejh(null);  
169 - updateList.add(curr);  
170 - }  
171 - prve = curr;  
172 - }  
173 -  
174 - return updateList;  
175 - }  
176 -  
177 - public SchAttrCalculator calcFcsjTime(ScheduleRealInfo sch) throws ParseException {  
178 - sch.setFcsjT(fmtyyyyMMddHHmm.parseMillis(sch.getRealExecDate() + sch.getFcsj()));  
179 - return this;  
180 - }  
181 -  
182 - public void calcTimestamp(ScheduleRealInfo sch) throws ParseException {  
183 - //计发时间  
184 - if (sch.getFcsjT() == null)  
185 - calcFcsjTime(sch);  
186 -  
187 - //待发时间  
188 - if (sch.getDfsj() == null)  
189 - sch.setDfsjAll(sch.getFcsjT());  
190 - if (sch.getDfsjT() == null)  
191 - sch.setDfsjAll(sch.getDfsj());  
192 -  
193 - //实发时间戳  
194 - if (sch.getFcsjActualTime() == null && sch.getFcsjActual() != null)  
195 - sch.setFcsjActualAll(sch.getFcsjActual());  
196 -  
197 - //实达时间戳  
198 - if (sch.getZdsjActualTime() == null && sch.getZdsjActual() != null)  
199 - sch.setZdsjActualAll(sch.getZdsjActual());  
200 - }  
201 -  
202 - /**  
203 - * 计算当前要执行的班次  
204 - *  
205 - * @param list  
206 - * @return  
207 - */  
208 - public ScheduleRealInfo calcCurrentExecSch(List<ScheduleRealInfo> list) {  
209 - if(list.size()==0)  
210 - return null;  
211 - String lineCode = list.get(0).getXlBm();  
212 - LineConfig conf = lineConfigData.get(lineCode);  
213 -  
214 - int outConfig = -1;  
215 - //限定出站既出场的停车场  
216 - List<String> parks = null;  
217 - if (conf != null) {  
218 - outConfig = conf.getOutConfig();  
219 - parks = conf.findTwinsParkList();  
220 - }  
221 - boolean limitPark = null != parks && parks.size() > 0;  
222 -  
223 - ScheduleRealInfo sch, prev = null;  
224 - for(int i = list.size() - 1; i >= 0; i --){  
225 - sch = list.get(i);  
226 -  
227 - //如果是出站既出场,忽略出场班次  
228 - if (outConfig == 2 && sch.getBcType().equals("out")  
229 - && (!limitPark || parks.contains(sch.getQdzCode()))  
230 - && (sch.getBcsj()==0 || sch.getJhlcOrig().intValue()==0))  
231 - continue;  
232 -  
233 - //忽略烂班  
234 - if (sch.isDestroy())  
235 - continue;  
236 -  
237 - if (StringUtils.isNotEmpty(sch.getZdsjActual()))  
238 - break;  
239 -  
240 - prev = sch;  
241 - }  
242 - return prev;  
243 - }  
244 -} 1 +package com.bsth.data.schedule;
  2 +
  3 +import com.bsth.data.LineConfigData;
  4 +import com.bsth.entity.realcontrol.LineConfig;
  5 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  6 +import org.apache.commons.lang3.StringUtils;
  7 +import org.joda.time.format.DateTimeFormat;
  8 +import org.joda.time.format.DateTimeFormatter;
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import java.text.ParseException;
  15 +import java.util.ArrayList;
  16 +import java.util.Collections;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * @author PanZhao
  21 + * @ClassName: SchAttrCalculator
  22 + * @Description: TODO(班次相关属性计算器)
  23 + * @date 2016年8月15日 下午4:40:26
  24 + */
  25 +@Component
  26 +public class SchAttrCalculator {
  27 +
  28 + @Autowired
  29 + LineConfigData lineConfigData;
  30 +
  31 + private final static long DAY_TIME = 1000 * 60 * 60 * 24L;
  32 +
  33 + Logger logger = LoggerFactory.getLogger(this.getClass());
  34 +
  35 + private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd"), fmtHHmm = DateTimeFormat.forPattern("HH:mm"), fmtyyyyMMddHHmm = DateTimeFormat.forPattern("yyyy-MM-ddHH:mm");
  36 +
  37 + /**
  38 + * @Title: calcRealDate
  39 + * @Description: TODO(计算班次的真实执行日期)
  40 + */
  41 + public SchAttrCalculator calcRealDate(ScheduleRealInfo sch) {
  42 + LineConfig conf = lineConfigData.get(sch.getXlBm());
  43 +
  44 + try {
  45 + if (null == sch.getFcsjT())
  46 + calcFcsjTime(sch);
  47 +
  48 + String rq = sch.getScheduleDateStr();
  49 + //计发時間
  50 + sch.setFcsjAll(getTime(rq, sch.getFcsj(), conf));
  51 +
  52 + //待发時間
  53 + sch.setDfsjAll(getTime(rq, sch.getDfsj(), conf));
  54 + /*if (sch.getDfsj().compareTo(conf.getStartOpt()) < 0) {
  55 + sch.setDfsjAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getDfsj()) + DAY_TIME);
  56 + } else
  57 + sch.setDfsjAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getDfsj()));*/
  58 +
  59 + //实发時間
  60 + sch.setFcsjActualAll(getTime(rq, sch.getFcsjActual(), conf));
  61 + /*if (StringUtils.isNotEmpty(sch.getFcsjActual()) &&
  62 + sch.getFcsjActual().compareTo(conf.getStartOpt()) < 0) {
  63 + sch.setFcsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getFcsjActual()) + DAY_TIME);
  64 + }*/
  65 +
  66 + //实际终点時間
  67 + sch.setZdsjActualAll(getTime(rq, sch.getZdsjActual(), conf));
  68 + /*if (StringUtils.isNotEmpty(sch.getZdsjActual()) &&
  69 + sch.getZdsjActual().compareTo(conf.getStartOpt()) < 0) {
  70 + sch.setZdsjActualAll(fmtyyyyMMddHHmm.parseMillis(sch.getScheduleDateStr() + sch.getZdsjActual()) + DAY_TIME);
  71 + }*/
  72 +
  73 + sch.setRealExecDate(fmtyyyyMMdd.print(sch.getFcsjT()));
  74 + } catch (Exception e) {
  75 + logger.error("", e);
  76 + }
  77 + return this;
  78 + }
  79 +
  80 + public Long getTime(String rq, String timeStr, LineConfig conf) {
  81 + Long t = null;
  82 + if (StringUtils.isNotEmpty(timeStr)) {
  83 + t = fmtyyyyMMddHHmm.parseMillis(rq + timeStr);
  84 + if(timeStr.compareTo(conf.getStartOpt()) < 0)
  85 + return t + DAY_TIME;
  86 + }
  87 + return t;
  88 + }
  89 +
  90 + /**
  91 + * @Title: calcAllTimeByFcsj
  92 + * @Description: TODO(根据发车时间字符串计算 (计发时间,终点时间,待发时间))
  93 + */
  94 + public SchAttrCalculator calcAllTimeByFcsj(ScheduleRealInfo sch) {
  95 + try {
  96 + // 生成时间戳
  97 + calcTimestamp(sch);
  98 +
  99 + // 计划终点时间
  100 + if (sch.getBcsj() != null) {
  101 + sch.setZdsjT(sch.getFcsjT() + (sch.getBcsj() * 60 * 1000));
  102 + sch.setZdsj(fmtHHmm.print(sch.getZdsjT()));
  103 + }
  104 + } catch (ParseException e) {
  105 + logger.error("", e);
  106 + }
  107 + return this;
  108 + }
  109 +
  110 + /**
  111 + * @Title: calcQdzTimePlan
  112 + * @Description: TODO(计算班次的起点应到时间)
  113 + */
  114 + public void calcQdzTimePlan(List<ScheduleRealInfo> list) {
  115 + Collections.sort(list, new ScheduleComparator.FCSJ());
  116 +
  117 + int len = list.size();
  118 + if (len == 0)
  119 + return;
  120 +
  121 + ScheduleRealInfo prve = list.get(0), curr;
  122 + for (int i = 1; i < len; i++) {
  123 + curr = list.get(i);
  124 +
  125 + if (isJoin(prve, curr)) {
  126 + curr.setQdzArrDatejh(prve.getZdsj());
  127 + if (StringUtils.isNotEmpty(prve.getZdsjActual()))
  128 + curr.setQdzArrDatesj(prve.getZdsjActual());
  129 + }
  130 + prve = curr;
  131 + }
  132 + }
  133 +
  134 + private boolean isJoin(ScheduleRealInfo prve, ScheduleRealInfo curr) {
  135 + return prve.getZdzName().equals(curr.getQdzName())//名称相等
  136 + || prve.getZdzCode().equals(curr.getQdzCode())//编码相等
  137 + || prve.getZdzName().startsWith(curr.getQdzName())//起始包括
  138 + || curr.getQdzName().startsWith(prve.getZdzName());//起始包括
  139 + }
  140 +
  141 + /**
  142 + * @Title: updateQdzTimePlan
  143 + * @Description: TODO(更新班次的起点应到时间) 并返回被更新的班次
  144 + */
  145 + public List<ScheduleRealInfo> updateQdzTimePlan(List<ScheduleRealInfo> list) {
  146 + Collections.sort(list, new ScheduleComparator.FCSJ());
  147 +
  148 + List<ScheduleRealInfo> updateList = new ArrayList<>();
  149 + int len = list.size();
  150 + if (len == 0)
  151 + return updateList;
  152 +
  153 + ScheduleRealInfo prve = list.get(0), curr;
  154 + for (int i = 1; i < len; i++) {
  155 + curr = list.get(i);
  156 +
  157 + if (prve.getZdzName().equals(curr.getQdzName())
  158 + || prve.getZdzCode().equals(curr.getQdzCode())) {
  159 +
  160 + if (curr.getQdzArrDatejh() != null && prve.getZdsj().equals(curr.getQdzArrDatejh())) {
  161 + prve = curr;
  162 + continue;
  163 + }
  164 +
  165 + curr.setQdzArrDatejh(prve.getZdsj());
  166 + updateList.add(curr);
  167 + } else {
  168 + curr.setQdzArrDatejh(null);
  169 + updateList.add(curr);
  170 + }
  171 + prve = curr;
  172 + }
  173 +
  174 + return updateList;
  175 + }
  176 +
  177 + public SchAttrCalculator calcFcsjTime(ScheduleRealInfo sch) throws ParseException {
  178 + sch.setFcsjT(fmtyyyyMMddHHmm.parseMillis(sch.getRealExecDate() + sch.getFcsj()));
  179 + return this;
  180 + }
  181 +
  182 + public void calcTimestamp(ScheduleRealInfo sch) throws ParseException {
  183 + //计发时间
  184 + if (sch.getFcsjT() == null)
  185 + calcFcsjTime(sch);
  186 +
  187 + //待发时间
  188 + if (sch.getDfsj() == null)
  189 + sch.setDfsjAll(sch.getFcsjT());
  190 + if (sch.getDfsjT() == null)
  191 + sch.setDfsjAll(sch.getDfsj());
  192 +
  193 + //实发时间戳
  194 + if (sch.getFcsjActualTime() == null && sch.getFcsjActual() != null)
  195 + sch.setFcsjActualAll(sch.getFcsjActual());
  196 +
  197 + //实达时间戳
  198 + if (sch.getZdsjActualTime() == null && sch.getZdsjActual() != null)
  199 + sch.setZdsjActualAll(sch.getZdsjActual());
  200 + }
  201 +
  202 + /**
  203 + * 计算当前要执行的班次
  204 + *
  205 + * @param list
  206 + * @return
  207 + */
  208 + public ScheduleRealInfo calcCurrentExecSch(List<ScheduleRealInfo> list) {
  209 + if(list.size()==0)
  210 + return null;
  211 + String lineCode = list.get(0).getXlBm();
  212 + LineConfig conf = lineConfigData.get(lineCode);
  213 +
  214 + int outConfig = -1;
  215 + //限定出站既出场的停车场
  216 + List<String> parks = null;
  217 + if (conf != null) {
  218 + outConfig = conf.getOutConfig();
  219 + parks = conf.findTwinsParkList();
  220 + }
  221 + boolean limitPark = null != parks && parks.size() > 0;
  222 +
  223 + ScheduleRealInfo sch, prev = null;
  224 + for(int i = list.size() - 1; i >= 0; i --){
  225 + sch = list.get(i);
  226 +
  227 + //如果是出站既出场,忽略出场班次
  228 + if (outConfig == 2 && sch.getBcType().equals("out")
  229 + && (!limitPark || parks.contains(sch.getQdzCode()))
  230 + && (sch.getBcsj()==0 || sch.getJhlcOrig().intValue()==0))
  231 + continue;
  232 +
  233 + //忽略烂班
  234 + if (sch.isDestroy())
  235 + continue;
  236 +
  237 + if (StringUtils.isNotEmpty(sch.getZdsjActual()) || sch.getStatus() == 2)
  238 + break;
  239 +
  240 + prev = sch;
  241 + }
  242 + return prev;
  243 + }
  244 +}
src/main/java/com/bsth/data/schedule/auto_exec/AfterServiceScheduler.java 0 → 100644
  1 +package com.bsth.data.schedule.auto_exec;
  2 +
  3 +import com.bsth.data.BasicData;
  4 +import com.bsth.data.LineConfigData;
  5 +import com.bsth.data.gpsdata_v2.cache.GeoCacheData;
  6 +import com.bsth.data.gpsdata_v2.entity.StationRoute;
  7 +import com.bsth.data.gpsdata_v2.utils.GeoUtils;
  8 +import com.bsth.data.schedule.DayOfSchedule;
  9 +import com.bsth.entity.realcontrol.LineConfig;
  10 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  11 +import com.bsth.util.Geo.Point;
  12 +import com.google.common.collect.ArrayListMultimap;
  13 +import com.google.common.collect.BiMap;
  14 +import com.google.common.collect.Multimap;
  15 +import org.joda.time.DateTime;
  16 +import org.joda.time.format.DateTimeFormat;
  17 +import org.joda.time.format.DateTimeFormatter;
  18 +import org.slf4j.Logger;
  19 +import org.slf4j.LoggerFactory;
  20 +import org.springframework.beans.factory.annotation.Autowired;
  21 +import org.springframework.beans.factory.annotation.Qualifier;
  22 +import org.springframework.jdbc.core.BeanPropertyRowMapper;
  23 +import org.springframework.jdbc.core.JdbcTemplate;
  24 +import org.springframework.scheduling.annotation.EnableScheduling;
  25 +import org.springframework.scheduling.annotation.Scheduled;
  26 +import org.springframework.stereotype.Component;
  27 +
  28 +import java.util.*;
  29 +
  30 +@Component
  31 +@EnableScheduling
  32 +public class AfterServiceScheduler {
  33 +
  34 + private final static Logger log = LoggerFactory.getLogger(AfterServiceScheduler.class);
  35 +
  36 + @Autowired
  37 + private LineConfigData lineConfigData;
  38 +
  39 + @Autowired
  40 + private DayOfSchedule dayOfSchedule;
  41 +
  42 + @Autowired
  43 + @Qualifier("msJdbcTemplate")
  44 + private JdbcTemplate msJdbcTemplate;
  45 +
  46 + private Map<String, String> complete = new HashMap<>();
  47 +
  48 + private DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
  49 +
  50 + private final static int MAX_DIFF = 3600000;
  51 +
  52 + /**
  53 + * 自动执行的线路,营运结束后未正常完成的班次重新匹配最近发车时间和到达时间
  54 + */
  55 + @Scheduled(cron = "0 15/30 * * * ?")
  56 + public void compute() {
  57 + log.warn("自动执行线路营运后计算开始");
  58 + Collection<LineConfig> lineConfigs = lineConfigData.getAll();
  59 + if (lineConfigs == null || lineConfigs.isEmpty()) {
  60 + return;
  61 + }
  62 + for (LineConfig lineConfig : lineConfigs) {
  63 + if (lineConfig.isAutoExec() && lineConfig.getAutoExecOffset() > 0) {
  64 + String lineCode = lineConfig.getLine().getLineCode();
  65 + String schDate = dayOfSchedule.getCurrSchDate().get(lineCode);
  66 + if (schDate == null) {
  67 + continue;
  68 + }
  69 + DateTime dateTime = formatter.parseDateTime(schDate);
  70 + if (!schDate.equals(complete.get(lineCode))) {
  71 + List<ScheduleRealInfo> schedules = dayOfSchedule.findByLineCode(lineCode);
  72 + Multimap<String, ScheduleRealInfo> multimap = ArrayListMultimap.create();
  73 + long lastTime = 0;
  74 + for (ScheduleRealInfo schedule : schedules) {
  75 + multimap.put(schedule.getClZbh(), schedule);
  76 + if (lastTime < schedule.getZdsjT()) {
  77 + lastTime = schedule.getZdsjT();
  78 + }
  79 + }
  80 + // 末班过后一个小时
  81 + if (lastTime + MAX_DIFF < System.currentTimeMillis()) {
  82 + BiMap<String, String> inside2device = BasicData.deviceId2NbbmMap.inverse();
  83 + for (String key : multimap.keySet()) {
  84 + String deviceId = inside2device.get(key);
  85 + Collection<ScheduleRealInfo> infos = multimap.get(key);
  86 + List<ScheduleRealInfo> list = new ArrayList<>(infos);
  87 + List<GpsInfo> gpsInfos = msJdbcTemplate.query("SELECT device_id,line_id,lon,lat,service_state,ts FROM bsth_c_gps_info_" + dateTime.getYear() + " WHERE days_year = ? AND device_id = ? AND service_state & 0x80000000 = 0 ORDER BY ts", new Object[]{dateTime.getDayOfYear(), deviceId}, BeanPropertyRowMapper.newInstance(GpsInfo.class));
  88 + for (ScheduleRealInfo schedule : list) {
  89 + if (schedule.getFcsjActual() == null || schedule.getZdsjActual() == null) {
  90 + matchTime(schedule, gpsInfos);
  91 + dayOfSchedule.save(schedule);
  92 + }
  93 + }
  94 + }
  95 + complete.put(lineCode, schDate);
  96 + }
  97 + }
  98 + }
  99 + }
  100 + }
  101 +
  102 + private void matchTime(ScheduleRealInfo schedule, List<GpsInfo> gpsInfos) {
  103 + List<StationRoute> srs = GeoCacheData.getStationRoute(schedule.getXlBm(), Integer.parseInt(schedule.getXlDir()));
  104 + String qdz = schedule.getQdzCode(), zdz = schedule.getZdzCode();
  105 + StationRoute qdzRoute = null, zdzRoute = null;
  106 + for (StationRoute route : srs) {
  107 + if (schedule.getFcsjActual() == null && qdz.equals(route.getCode())) {
  108 + qdzRoute = route;
  109 + }
  110 + if (schedule.getZdsjActual() == null && zdz.equals(route.getCode())) {
  111 + zdzRoute = route;
  112 + break;
  113 + }
  114 + }
  115 + int qdzIdx = -1, qdzIdx2 = -1, count = 0;
  116 + for (GpsInfo gpsInfo : gpsInfos) {
  117 + if (qdzRoute != null && gpsInfo.getTs() < schedule.getFcsjT() && GeoUtils.isGpsInSpecialStation(qdzRoute, new Point(gpsInfo.getLon(), gpsInfo.getLat()))) {
  118 + qdzIdx = count;
  119 + }
  120 + if (qdzIdx2 == -1 && qdzRoute != null && gpsInfo.getTs() > schedule.getFcsjT() && GeoUtils.isGpsInSpecialStation(qdzRoute, new Point(gpsInfo.getLon(), gpsInfo.getLat()))) {
  121 + qdzIdx2 = count;
  122 + }
  123 + if (zdzRoute != null && gpsInfo.getTs() > schedule.getFcsjT() && GeoUtils.isGpsInSpecialStation(zdzRoute, new Point(gpsInfo.getLon(), gpsInfo.getLat()))) {
  124 + schedule.setZdsjActual(new DateTime(gpsInfo.getTs()).toString("HH:mm"));
  125 + schedule.setZdsjActualTime(gpsInfo.getTs());
  126 + break;
  127 + }
  128 + count++;
  129 + }
  130 + if (qdzIdx > -1 && qdzIdx2 > -1) {
  131 + GpsInfo gpsInfo1 = gpsInfos.get(qdzIdx), gpsInfo2 = gpsInfos.get(qdzIdx2);
  132 + if (Math.abs(schedule.getFcsjT() - gpsInfo1.getTs()) >= Math.abs(schedule.getFcsjT() - gpsInfo2.getTs()) && qdzIdx2 < gpsInfos.size() - 1) {
  133 + qdzIdx = qdzIdx2;
  134 + }
  135 + } else if (qdzIdx2 > -1) {
  136 + qdzIdx = qdzIdx2;
  137 + }
  138 + if (qdzIdx > -1 && qdzIdx < gpsInfos.size() - 1) {
  139 + for (int i = qdzIdx + 1;i < gpsInfos.size(); i++) {
  140 + GpsInfo gpsInfo = gpsInfos.get(i);
  141 + if (!GeoUtils.isGpsInSpecialStation(qdzRoute, new Point(gpsInfo.getLon(), gpsInfo.getLat()))) {
  142 + schedule.setFcsjActual(new DateTime(gpsInfo.getTs()).toString("HH:mm"));
  143 + schedule.setFcsjActualTime(gpsInfo.getTs());
  144 + break;
  145 + }
  146 + }
  147 + }
  148 + }
  149 +
  150 + public static class GpsInfo {
  151 +
  152 + private String deviceId;
  153 +
  154 + private int lineId;
  155 +
  156 + private float lon;
  157 +
  158 + private float lat;
  159 +
  160 + private long serviceState;
  161 +
  162 + private long ts;
  163 +
  164 + public GpsInfo() {
  165 +
  166 + }
  167 +
  168 + public String getDeviceId() {
  169 + return deviceId;
  170 + }
  171 +
  172 + public void setDeviceId(String deviceId) {
  173 + this.deviceId = deviceId;
  174 + }
  175 +
  176 + public int getLineId() {
  177 + return lineId;
  178 + }
  179 +
  180 + public void setLineId(int lineId) {
  181 + this.lineId = lineId;
  182 + }
  183 +
  184 + public float getLon() {
  185 + return lon;
  186 + }
  187 +
  188 + public void setLon(float lon) {
  189 + this.lon = lon;
  190 + }
  191 +
  192 + public float getLat() {
  193 + return lat;
  194 + }
  195 +
  196 + public void setLat(float lat) {
  197 + this.lat = lat;
  198 + }
  199 +
  200 + public long getServiceState() {
  201 + return serviceState;
  202 + }
  203 +
  204 + public void setServiceState(long serviceState) {
  205 + this.serviceState = serviceState;
  206 + }
  207 +
  208 + public long getTs() {
  209 + return ts;
  210 + }
  211 +
  212 + public void setTs(long ts) {
  213 + this.ts = ts;
  214 + }
  215 + }
  216 +}
src/main/java/com/bsth/data/schedule/auto_exec/AutoExecScanThread.java
@@ -9,9 +9,7 @@ import org.slf4j.LoggerFactory; @@ -9,9 +9,7 @@ import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
11 11
12 -import java.util.ArrayList;  
13 -import java.util.Collection;  
14 -import java.util.List; 12 +import java.util.*;
15 13
16 /** 14 /**
17 * 班次自动执行扫描线程 15 * 班次自动执行扫描线程
@@ -39,9 +37,11 @@ public class AutoExecScanThread extends Thread{ @@ -39,9 +37,11 @@ public class AutoExecScanThread extends Thread{
39 //要自动执行的线路 37 //要自动执行的线路
40 List<String> autos = new ArrayList<>(); 38 List<String> autos = new ArrayList<>();
41 Collection<LineConfig> lcs = lineConfigData.getAll(); 39 Collection<LineConfig> lcs = lineConfigData.getAll();
  40 + Map<String, LineConfig> line2config = new HashMap<>();
42 41
43 for(LineConfig config : lcs){ 42 for(LineConfig config : lcs){
44 if(config.isAutoExec()){ 43 if(config.isAutoExec()){
  44 + line2config.put(config.getLine().getLineCode(), config);
45 autos.add(config.getLine().getLineCode()); 45 autos.add(config.getLine().getLineCode());
46 } 46 }
47 } 47 }
@@ -51,7 +51,14 @@ public class AutoExecScanThread extends Thread{ @@ -51,7 +51,14 @@ public class AutoExecScanThread extends Thread{
51 List<ScheduleRealInfo> all = new ArrayList<>(dayOfSchedule.findAll()); 51 List<ScheduleRealInfo> all = new ArrayList<>(dayOfSchedule.findAll());
52 for(ScheduleRealInfo sch : all){ 52 for(ScheduleRealInfo sch : all){
53 if(autos.contains(sch.getXlBm())){ 53 if(autos.contains(sch.getXlBm())){
54 - realScheduleAutoExecHandler.exec(sch); 54 + LineConfig config = line2config.get(sch.getXlBm());
  55 + if (config != null) {
  56 + if (config.getAutoExecOffset() == 0) {
  57 + realScheduleAutoExecHandler.exec(sch);
  58 + } else if (config.getAutoExecOffset() > 0) {
  59 + realScheduleAutoExecHandler.exec1(sch, config);
  60 + }
  61 + }
55 } 62 }
56 } 63 }
57 }catch (Exception e){ 64 }catch (Exception e){
src/main/java/com/bsth/data/schedule/auto_exec/RealScheduleAutoExecHandler.java
1 -package com.bsth.data.schedule.auto_exec;  
2 -  
3 -import com.bsth.data.gpsdata_v2.status_manager.GpsStatusManager;  
4 -import com.bsth.data.schedule.DayOfSchedule;  
5 -import com.bsth.entity.realcontrol.ScheduleRealInfo;  
6 -import com.bsth.websocket.handler.SendUtils;  
7 -import org.apache.commons.lang3.StringUtils;  
8 -import org.springframework.beans.factory.annotation.Autowired;  
9 -import org.springframework.stereotype.Component;  
10 -  
11 -import java.util.ArrayList;  
12 -import java.util.List;  
13 -  
14 -/**  
15 - * 实际班次自动执行  
16 - * Created by panzhao on 2017/10/31.  
17 - */  
18 -@Component  
19 -public class RealScheduleAutoExecHandler {  
20 -  
21 - @Autowired  
22 - SendUtils sendUtils;  
23 - @Autowired  
24 - DayOfSchedule dayOfSchedule;  
25 -  
26 - @Autowired  
27 - GpsStatusManager gpsStatusManager;  
28 -  
29 - public void exec(ScheduleRealInfo sch) {  
30 - boolean flag = false;  
31 - long t = System.currentTimeMillis();  
32 -  
33 - if (StringUtils.isEmpty(sch.getFcsjActual()) && sch.getDfsjT() < t) {  
34 - sch.setFcsjActualAll(sch.getDfsjT());  
35 - flag = true;  
36 - }  
37 -  
38 - if (StringUtils.isEmpty(sch.getZdsjActual()) && sch.getZdsjT() < t) {  
39 - sch.setZdsjActualAll(sch.getZdsjT());  
40 - flag = true;  
41 -  
42 - //准备执行下一个班次  
43 - ScheduleRealInfo next = dayOfSchedule.next(sch);  
44 - if (next != null) {  
45 - dayOfSchedule.addExecPlan(next);  
46 - //套跑 -下发线路切换指令  
47 - if(!next.getXlBm().equals(sch.getXlBm())){  
48 - gpsStatusManager.changeLine(next.getClZbh(), next.getXlBm(), "auto@系统");  
49 - }  
50 - }  
51 -  
52 - //路牌有下一个班次,线调页面显示  
53 - ScheduleRealInfo nextLp = dayOfSchedule.nextByLp(sch);  
54 - if (null != nextLp) {  
55 - //入库  
56 - dayOfSchedule.save(sch);  
57 -  
58 - nextLp.setQdzArrDatesj(sch.getZdsjActual());  
59 - List<ScheduleRealInfo> refs = new ArrayList<>();  
60 - refs.add(sch);  
61 - refs.add(nextLp);  
62 - sendUtils.refreshSch(refs);  
63 - return;  
64 - }  
65 - }  
66 -  
67 - if (flag) {  
68 - dayOfSchedule.save(sch);  
69 - sendUtils.refreshSch(sch);  
70 - }  
71 - }  
72 -} 1 +package com.bsth.data.schedule.auto_exec;
  2 +
  3 +import com.bsth.data.gpsdata_v2.status_manager.GpsStatusManager;
  4 +import com.bsth.data.msg_queue.DirectivePushQueue;
  5 +import com.bsth.data.schedule.DayOfSchedule;
  6 +import com.bsth.entity.realcontrol.LineConfig;
  7 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  8 +import com.bsth.websocket.handler.SendUtils;
  9 +import org.apache.commons.lang3.StringUtils;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import java.util.ArrayList;
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * 实际班次自动执行
  18 + * Created by panzhao on 2017/10/31.
  19 + */
  20 +@Component
  21 +public class RealScheduleAutoExecHandler {
  22 +
  23 + @Autowired
  24 + SendUtils sendUtils;
  25 + @Autowired
  26 + DayOfSchedule dayOfSchedule;
  27 +
  28 + @Autowired
  29 + GpsStatusManager gpsStatusManager;
  30 +
  31 + /**
  32 + * 自动执行偏差为0的处理
  33 + * @param sch
  34 + */
  35 + public void exec(ScheduleRealInfo sch) {
  36 + boolean flag = false;
  37 + long t = System.currentTimeMillis();
  38 +
  39 + if (StringUtils.isEmpty(sch.getFcsjActual()) && sch.getDfsjT() < t) {
  40 + sch.setFcsjActualAll(sch.getDfsjT());
  41 + flag = true;
  42 + }
  43 +
  44 + if (StringUtils.isEmpty(sch.getZdsjActual()) && sch.getZdsjT() < t) {
  45 + sch.setZdsjActualAll(sch.getZdsjT());
  46 + flag = true;
  47 +
  48 + //准备执行下一个班次
  49 + ScheduleRealInfo next = dayOfSchedule.next(sch);
  50 + if (next != null) {
  51 + dayOfSchedule.addExecPlan(next);
  52 + //套跑 -下发线路切换指令
  53 + if(!next.getXlBm().equals(sch.getXlBm())){
  54 + gpsStatusManager.changeLine(next.getClZbh(), next.getXlBm(), "auto@系统");
  55 + }
  56 + //已完成班次数
  57 + int doneSum = dayOfSchedule.doneSum(sch.getClZbh());
  58 + //下发调度指令
  59 + DirectivePushQueue.put6002(next, doneSum, "到站@系统", "");
  60 + }
  61 +
  62 + //路牌有下一个班次,线调页面显示
  63 + ScheduleRealInfo nextLp = dayOfSchedule.nextByLp(sch);
  64 + if (null != nextLp) {
  65 + //入库
  66 + dayOfSchedule.save(sch);
  67 +
  68 + nextLp.setQdzArrDatesj(sch.getZdsjActual());
  69 + List<ScheduleRealInfo> refs = new ArrayList<>();
  70 + refs.add(sch);
  71 + refs.add(nextLp);
  72 + sendUtils.refreshSch(refs);
  73 + return;
  74 + }
  75 + }
  76 +
  77 + if (flag) {
  78 + dayOfSchedule.save(sch);
  79 + sendUtils.refreshSch(sch);
  80 + }
  81 + }
  82 +
  83 + /**
  84 + * 自动执行偏差不为0的处理
  85 + * @param sch
  86 + */
  87 + public void exec1(ScheduleRealInfo sch, LineConfig lineConfig) {
  88 + long now = System.currentTimeMillis();
  89 + if (sch.getStatus() == 2 || sch.getStatus() == -1) {
  90 + return;
  91 + }
  92 + // 如果超过了最大自动执行偏移时间 执行下一个班次
  93 + if (now > sch.getZdsjT() + lineConfig.getAutoExecOffset() * 60000) {
  94 + //标记班次为完成
  95 + sch.setStatus(2);
  96 + //准备执行下一个班次
  97 + ScheduleRealInfo next = dayOfSchedule.next(sch);
  98 + if (next != null) {
  99 + dayOfSchedule.addExecPlan(next);
  100 + //套跑 -下发线路切换指令
  101 + if(!next.getXlBm().equals(sch.getXlBm())){
  102 + gpsStatusManager.changeLine(next.getClZbh(), next.getXlBm(), "auto@系统");
  103 + }
  104 + //已完成班次数
  105 + int doneSum = dayOfSchedule.doneSum(sch.getClZbh());
  106 + //下发调度指令
  107 + DirectivePushQueue.put6002(next, doneSum, "到站@系统", "");
  108 + } else {
  109 + dayOfSchedule.removeExecPlan(sch.getClZbh());
  110 + }
  111 +
  112 + //路牌有下一个班次,线调页面显示
  113 + ScheduleRealInfo nextLp = dayOfSchedule.nextByLp(sch);
  114 + if (null != nextLp) {
  115 + //入库
  116 + dayOfSchedule.save(sch);
  117 +
  118 + nextLp.setQdzArrDatesj(sch.getZdsjActual());
  119 + List<ScheduleRealInfo> refs = new ArrayList<>();
  120 + refs.add(sch);
  121 + refs.add(nextLp);
  122 + sendUtils.refreshSch(refs);
  123 + }
  124 + }
  125 + }
  126 +}
src/main/java/com/bsth/entity/realcontrol/LineConfig.java
@@ -58,6 +58,11 @@ public class LineConfig { @@ -58,6 +58,11 @@ public class LineConfig {
58 private boolean autoExec; 58 private boolean autoExec;
59 59
60 /** 60 /**
  61 + * 自动执行偏差值(分钟)
  62 + */
  63 + private int autoExecOffset;
  64 +
  65 + /**
61 * 到离站偏移值 66 * 到离站偏移值
62 */ 67 */
63 68
@@ -232,6 +237,14 @@ public class LineConfig { @@ -232,6 +237,14 @@ public class LineConfig {
232 this.autoExec = autoExec; 237 this.autoExec = autoExec;
233 } 238 }
234 239
  240 + public int getAutoExecOffset() {
  241 + return autoExecOffset;
  242 + }
  243 +
  244 + public void setAutoExecOffset(int autoExecOffset) {
  245 + this.autoExecOffset = autoExecOffset;
  246 + }
  247 +
235 public String getTwinsParks() { 248 public String getTwinsParks() {
236 return twinsParks; 249 return twinsParks;
237 } 250 }
src/main/java/com/bsth/service/realcontrol/impl/LineConfigServiceImpl.java
1 -package com.bsth.service.realcontrol.impl;  
2 -  
3 -import com.bsth.common.ResponseCode;  
4 -import com.bsth.data.LineConfigData;  
5 -import com.bsth.entity.realcontrol.LineConfig;  
6 -import com.bsth.repository.realcontrol.LineConfigRepository;  
7 -import com.bsth.service.impl.BaseServiceImpl;  
8 -import com.bsth.service.realcontrol.LineConfigService;  
9 -import com.google.common.base.Splitter;  
10 -import org.slf4j.Logger;  
11 -import org.slf4j.LoggerFactory;  
12 -import org.springframework.beans.factory.annotation.Autowired;  
13 -import org.springframework.stereotype.Service;  
14 -  
15 -import java.lang.reflect.Field;  
16 -import java.util.ArrayList;  
17 -import java.util.HashMap;  
18 -import java.util.List;  
19 -import java.util.Map;  
20 -  
21 -@Service  
22 -public class LineConfigServiceImpl extends BaseServiceImpl<LineConfig, Integer> implements LineConfigService {  
23 -  
24 - @Autowired  
25 - LineConfigRepository lineConfigRepository;  
26 -  
27 - @Autowired  
28 - LineConfigData lineConfigData;  
29 -  
30 - Logger logger = LoggerFactory.getLogger(this.getClass());  
31 -  
32 - @Override  
33 - public Map<String, Object> check(String[] codeArray) {  
34 - Map<String, Object> rs = new HashMap<>();  
35 - List<String> notArr = new ArrayList<>();  
36 -  
37 - for (String lineCode : codeArray) {  
38 - if (null == lineConfigData.get(lineCode + ""))  
39 - notArr.add(lineCode);  
40 - }  
41 -  
42 - if (notArr.size() > 0) {  
43 - rs.put("status", 1);  
44 - rs.put("not", notArr);  
45 - } else  
46 - rs.put("status", 0);  
47 - return rs;  
48 - }  
49 -  
50 - @Override  
51 - public Integer init(String lineCode) throws Exception {  
52 - LineConfig conf = lineConfigData.get(lineCode);  
53 -  
54 - if (conf == null)  
55 - lineConfigData.init(lineCode);  
56 -  
57 - return 1;  
58 - }  
59 -  
60 - @Override  
61 - public Map<String, Object> editStartOptTime(String time, String lineCode) {  
62 - Map<String, Object> rs = new HashMap<>();  
63 - try {  
64 - LineConfig conf = lineConfigData.get(lineCode);  
65 - conf.setStartOpt(time);  
66 - lineConfigData.set(conf);  
67 -  
68 - rs.put("status", ResponseCode.SUCCESS);  
69 - rs.put("time", time);  
70 - } catch (Exception e) {  
71 - rs.put("status", ResponseCode.ERROR);  
72 - rs.put("msg", e.getMessage());  
73 - logger.error("", e);  
74 - }  
75 - return rs;  
76 - }  
77 -  
78 - @Override  
79 - public Map<String, Object> editOutTimeType(String lineCode, int type, String parkCode, String stationCode) {  
80 - Map<String, Object> rs = new HashMap<>();  
81 - try {  
82 - LineConfig conf = lineConfigData.get(lineCode);  
83 -  
84 - conf.setOutConfig(type);  
85 - if(type == 2){  
86 - conf.setTwinsParks(parkCode);  
87 - conf.setTwinsStations(stationCode);  
88 - }  
89 - lineConfigData.set(conf);  
90 -  
91 - rs.put("status", ResponseCode.SUCCESS);  
92 - rs.put("conf", conf);  
93 - } catch (Exception e) {  
94 - rs.put("status", ResponseCode.ERROR);  
95 - rs.put("msg", e.getMessage());  
96 - logger.error("", e);  
97 - }  
98 - return rs;  
99 - }  
100 -  
101 - @Override  
102 - public LineConfig getByLineCode(String lineCode) {  
103 - return lineConfigData.get(lineCode);  
104 - }  
105 -  
106 - @Override  
107 - public Map<String, Object> enableInParkForSource(String lineCode, int enable) {  
108 - Map<String, Object> rs = new HashMap<>();  
109 - try {  
110 - LineConfig conf = lineConfigData.get(lineCode);  
111 -  
112 - conf.setInParkForSource(enable == 1);  
113 - lineConfigData.set(conf);  
114 -  
115 - rs.put("status", ResponseCode.SUCCESS);  
116 - rs.put("enable", enable);  
117 - } catch (Exception e) {  
118 - rs.put("status", ResponseCode.ERROR);  
119 - rs.put("msg", e.getMessage());  
120 - logger.error("", e);  
121 - }  
122 - return rs;  
123 - }  
124 -  
125 - @Override  
126 - public Map<String, Object> bufferTimeDiff(String lineCode, String field, String value) {  
127 -  
128 - Map<String, Object> rs = new HashMap<>();  
129 - try {  
130 - LineConfig conf = lineConfigData.get(lineCode);  
131 - Field f = conf.getClass().getDeclaredField(field);  
132 - f.setAccessible(true);  
133 - f.setInt(conf, Integer.parseInt(value));  
134 -  
135 - lineConfigData.set(conf);  
136 -  
137 - rs.put("status", ResponseCode.SUCCESS);  
138 - rs.put("field", field);  
139 - rs.put("value", value);  
140 - } catch (Exception e) {  
141 - rs.put("status", ResponseCode.ERROR);  
142 - rs.put("msg", e.getMessage());  
143 - logger.error("", e);  
144 - }  
145 - return rs;  
146 - }  
147 -  
148 - @Override  
149 - public Map<String, Object> yjtkSet(Map<String, String> map) {  
150 - String lineCode = map.get("lineCode").toString();  
151 - int enableYjtk = Integer.parseInt(map.get("enableYjtk").toString());  
152 -  
153 - Map<String, Object> rs = new HashMap<>();  
154 - try {  
155 - LineConfig conf = lineConfigData.get(lineCode);  
156 -  
157 - if(enableYjtk == 1){  
158 - String yjtkStart = map.containsKey("yjtkStart") ? map.get("yjtkStart").toString() : "00:00";  
159 - String yjtkEnd = map.containsKey("yjtkEnd") ? map.get("yjtkEnd").toString() : "23:59";  
160 - int upStopMinute = Integer.parseInt(map.get("upStopMinute").toString());  
161 - int downStopMinute = Integer.parseInt(map.get("downStopMinute").toString());  
162 -  
163 - conf.setEnableYjtk(true);  
164 - conf.setYjtkStart(yjtkStart);  
165 - conf.setYjtkEnd(yjtkEnd);  
166 - conf.setUpStopMinute(upStopMinute);  
167 - conf.setDownStopMinute(downStopMinute);  
168 - }  
169 - else  
170 - conf.setEnableYjtk(false);  
171 -  
172 - lineConfigData.set(conf);  
173 -  
174 - rs.put("status", ResponseCode.SUCCESS);  
175 - rs.put("conf", conf);  
176 - } catch (Exception e) {  
177 - rs.put("status", ResponseCode.ERROR);  
178 - rs.put("msg", e.getMessage());  
179 - logger.error("", e);  
180 - }  
181 - return rs;  
182 - }  
183 -  
184 - @Override  
185 - public Map<String, Object> parkAndStationSet(Map<String, String> map) {  
186 - String lineCode = map.get("lineCode").toString();  
187 - String twinsPark = map.get("twinsPark").toString();  
188 - String twinsStation = map.get("twinsStation").toString();  
189 -  
190 - Map<String, Object> rs = new HashMap<>();  
191 - try {  
192 - LineConfig conf = lineConfigData.get(lineCode);  
193 - conf.setTwinsParks(twinsPark);  
194 - conf.setTwinsStations(twinsStation);  
195 -  
196 - lineConfigData.set(conf);  
197 -  
198 - rs.put("status", ResponseCode.SUCCESS);  
199 - rs.put("conf", conf);  
200 - } catch (Exception e) {  
201 - rs.put("status", ResponseCode.ERROR);  
202 - rs.put("msg", e.getMessage());  
203 - logger.error("", e);  
204 - }  
205 - return rs;  
206 - }  
207 -  
208 - @Override  
209 - public Map<String, Object> findByIdx(String idx) {  
210 - Map<String, Object> rs = new HashMap();  
211 - try{  
212 - List<LineConfig> list = new ArrayList<>();  
213 - List<String> ids = Splitter.on(",").splitToList(idx);  
214 -  
215 - for(String id : ids){  
216 - list.add(lineConfigData.get(id));  
217 - }  
218 -  
219 - rs.put("status", ResponseCode.SUCCESS);  
220 - rs.put("list", list);  
221 - }catch (Exception e){  
222 - rs.put("status", ResponseCode.ERROR);  
223 - logger.error("", e);  
224 - }  
225 - return rs;  
226 - }  
227 -  
228 - @Override  
229 - public Map<String, Object> setAutoExec(Map<String, String> map) {  
230 - String lineCode = map.get("lineCode").toString();  
231 - boolean autoExec = Boolean.parseBoolean(map.get("autoExec").toString());  
232 -  
233 - Map<String, Object> rs = new HashMap<>();  
234 - try {  
235 - LineConfig conf = lineConfigData.get(lineCode);  
236 - conf.setAutoExec(autoExec);  
237 -  
238 - lineConfigData.set(conf);  
239 - rs.put("status", ResponseCode.SUCCESS);  
240 - rs.put("conf", conf);  
241 - } catch (Exception e) {  
242 - rs.put("status", ResponseCode.ERROR);  
243 - rs.put("msg", e.getMessage());  
244 - logger.error("", e);  
245 - }  
246 - return rs;  
247 - }  
248 -  
249 - @Override  
250 - public Map<String, Object> setReadReverse(int status, String lineCode) {  
251 - Map<String, Object> rs = new HashMap<>();  
252 - try {  
253 - LineConfig conf = lineConfigData.get(lineCode);  
254 - conf.setReadReverse(status==1?true:false);  
255 -  
256 - lineConfigData.set(conf);  
257 - rs.put("status", ResponseCode.SUCCESS);  
258 - rs.put("conf", conf);  
259 - } catch (Exception e) {  
260 - rs.put("status", ResponseCode.ERROR);  
261 - rs.put("msg", e.getMessage());  
262 - logger.error("", e);  
263 - }  
264 - return rs;  
265 - }  
266 -} 1 +package com.bsth.service.realcontrol.impl;
  2 +
  3 +import com.bsth.common.ResponseCode;
  4 +import com.bsth.data.LineConfigData;
  5 +import com.bsth.entity.realcontrol.LineConfig;
  6 +import com.bsth.repository.realcontrol.LineConfigRepository;
  7 +import com.bsth.service.impl.BaseServiceImpl;
  8 +import com.bsth.service.realcontrol.LineConfigService;
  9 +import com.google.common.base.Splitter;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.stereotype.Service;
  14 +
  15 +import java.lang.reflect.Field;
  16 +import java.util.ArrayList;
  17 +import java.util.HashMap;
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +
  21 +@Service
  22 +public class LineConfigServiceImpl extends BaseServiceImpl<LineConfig, Integer> implements LineConfigService {
  23 +
  24 + @Autowired
  25 + LineConfigRepository lineConfigRepository;
  26 +
  27 + @Autowired
  28 + LineConfigData lineConfigData;
  29 +
  30 + Logger logger = LoggerFactory.getLogger(this.getClass());
  31 +
  32 + @Override
  33 + public Map<String, Object> check(String[] codeArray) {
  34 + Map<String, Object> rs = new HashMap<>();
  35 + List<String> notArr = new ArrayList<>();
  36 +
  37 + for (String lineCode : codeArray) {
  38 + if (null == lineConfigData.get(lineCode + ""))
  39 + notArr.add(lineCode);
  40 + }
  41 +
  42 + if (notArr.size() > 0) {
  43 + rs.put("status", 1);
  44 + rs.put("not", notArr);
  45 + } else
  46 + rs.put("status", 0);
  47 + return rs;
  48 + }
  49 +
  50 + @Override
  51 + public Integer init(String lineCode) throws Exception {
  52 + LineConfig conf = lineConfigData.get(lineCode);
  53 +
  54 + if (conf == null)
  55 + lineConfigData.init(lineCode);
  56 +
  57 + return 1;
  58 + }
  59 +
  60 + @Override
  61 + public Map<String, Object> editStartOptTime(String time, String lineCode) {
  62 + Map<String, Object> rs = new HashMap<>();
  63 + try {
  64 + LineConfig conf = lineConfigData.get(lineCode);
  65 + conf.setStartOpt(time);
  66 + lineConfigData.set(conf);
  67 +
  68 + rs.put("status", ResponseCode.SUCCESS);
  69 + rs.put("time", time);
  70 + } catch (Exception e) {
  71 + rs.put("status", ResponseCode.ERROR);
  72 + rs.put("msg", e.getMessage());
  73 + logger.error("", e);
  74 + }
  75 + return rs;
  76 + }
  77 +
  78 + @Override
  79 + public Map<String, Object> editOutTimeType(String lineCode, int type, String parkCode, String stationCode) {
  80 + Map<String, Object> rs = new HashMap<>();
  81 + try {
  82 + LineConfig conf = lineConfigData.get(lineCode);
  83 +
  84 + conf.setOutConfig(type);
  85 + if(type == 2){
  86 + conf.setTwinsParks(parkCode);
  87 + conf.setTwinsStations(stationCode);
  88 + }
  89 + lineConfigData.set(conf);
  90 +
  91 + rs.put("status", ResponseCode.SUCCESS);
  92 + rs.put("conf", conf);
  93 + } catch (Exception e) {
  94 + rs.put("status", ResponseCode.ERROR);
  95 + rs.put("msg", e.getMessage());
  96 + logger.error("", e);
  97 + }
  98 + return rs;
  99 + }
  100 +
  101 + @Override
  102 + public LineConfig getByLineCode(String lineCode) {
  103 + return lineConfigData.get(lineCode);
  104 + }
  105 +
  106 + @Override
  107 + public Map<String, Object> enableInParkForSource(String lineCode, int enable) {
  108 + Map<String, Object> rs = new HashMap<>();
  109 + try {
  110 + LineConfig conf = lineConfigData.get(lineCode);
  111 +
  112 + conf.setInParkForSource(enable == 1);
  113 + lineConfigData.set(conf);
  114 +
  115 + rs.put("status", ResponseCode.SUCCESS);
  116 + rs.put("enable", enable);
  117 + } catch (Exception e) {
  118 + rs.put("status", ResponseCode.ERROR);
  119 + rs.put("msg", e.getMessage());
  120 + logger.error("", e);
  121 + }
  122 + return rs;
  123 + }
  124 +
  125 + @Override
  126 + public Map<String, Object> bufferTimeDiff(String lineCode, String field, String value) {
  127 +
  128 + Map<String, Object> rs = new HashMap<>();
  129 + try {
  130 + LineConfig conf = lineConfigData.get(lineCode);
  131 + Field f = conf.getClass().getDeclaredField(field);
  132 + f.setAccessible(true);
  133 + f.setInt(conf, Integer.parseInt(value));
  134 +
  135 + lineConfigData.set(conf);
  136 +
  137 + rs.put("status", ResponseCode.SUCCESS);
  138 + rs.put("field", field);
  139 + rs.put("value", value);
  140 + } catch (Exception e) {
  141 + rs.put("status", ResponseCode.ERROR);
  142 + rs.put("msg", e.getMessage());
  143 + logger.error("", e);
  144 + }
  145 + return rs;
  146 + }
  147 +
  148 + @Override
  149 + public Map<String, Object> yjtkSet(Map<String, String> map) {
  150 + String lineCode = map.get("lineCode").toString();
  151 + int enableYjtk = Integer.parseInt(map.get("enableYjtk").toString());
  152 +
  153 + Map<String, Object> rs = new HashMap<>();
  154 + try {
  155 + LineConfig conf = lineConfigData.get(lineCode);
  156 +
  157 + if(enableYjtk == 1){
  158 + String yjtkStart = map.containsKey("yjtkStart") ? map.get("yjtkStart").toString() : "00:00";
  159 + String yjtkEnd = map.containsKey("yjtkEnd") ? map.get("yjtkEnd").toString() : "23:59";
  160 + int upStopMinute = Integer.parseInt(map.get("upStopMinute").toString());
  161 + int downStopMinute = Integer.parseInt(map.get("downStopMinute").toString());
  162 +
  163 + conf.setEnableYjtk(true);
  164 + conf.setYjtkStart(yjtkStart);
  165 + conf.setYjtkEnd(yjtkEnd);
  166 + conf.setUpStopMinute(upStopMinute);
  167 + conf.setDownStopMinute(downStopMinute);
  168 + }
  169 + else
  170 + conf.setEnableYjtk(false);
  171 +
  172 + lineConfigData.set(conf);
  173 +
  174 + rs.put("status", ResponseCode.SUCCESS);
  175 + rs.put("conf", conf);
  176 + } catch (Exception e) {
  177 + rs.put("status", ResponseCode.ERROR);
  178 + rs.put("msg", e.getMessage());
  179 + logger.error("", e);
  180 + }
  181 + return rs;
  182 + }
  183 +
  184 + @Override
  185 + public Map<String, Object> parkAndStationSet(Map<String, String> map) {
  186 + String lineCode = map.get("lineCode").toString();
  187 + String twinsPark = map.get("twinsPark").toString();
  188 + String twinsStation = map.get("twinsStation").toString();
  189 +
  190 + Map<String, Object> rs = new HashMap<>();
  191 + try {
  192 + LineConfig conf = lineConfigData.get(lineCode);
  193 + conf.setTwinsParks(twinsPark);
  194 + conf.setTwinsStations(twinsStation);
  195 +
  196 + lineConfigData.set(conf);
  197 +
  198 + rs.put("status", ResponseCode.SUCCESS);
  199 + rs.put("conf", conf);
  200 + } catch (Exception e) {
  201 + rs.put("status", ResponseCode.ERROR);
  202 + rs.put("msg", e.getMessage());
  203 + logger.error("", e);
  204 + }
  205 + return rs;
  206 + }
  207 +
  208 + @Override
  209 + public Map<String, Object> findByIdx(String idx) {
  210 + Map<String, Object> rs = new HashMap();
  211 + try{
  212 + List<LineConfig> list = new ArrayList<>();
  213 + List<String> ids = Splitter.on(",").splitToList(idx);
  214 +
  215 + for(String id : ids){
  216 + list.add(lineConfigData.get(id));
  217 + }
  218 +
  219 + rs.put("status", ResponseCode.SUCCESS);
  220 + rs.put("list", list);
  221 + }catch (Exception e){
  222 + rs.put("status", ResponseCode.ERROR);
  223 + logger.error("", e);
  224 + }
  225 + return rs;
  226 + }
  227 +
  228 + @Override
  229 + public Map<String, Object> setAutoExec(Map<String, String> map) {
  230 + String lineCode = map.get("lineCode").toString();
  231 + boolean autoExec = Boolean.parseBoolean(map.get("autoExec"));
  232 + int autoExecOffset = Integer.parseInt(map.get("autoExecOffset"));
  233 +
  234 + Map<String, Object> rs = new HashMap<>();
  235 + try {
  236 + LineConfig conf = lineConfigData.get(lineCode);
  237 + conf.setAutoExec(autoExec);
  238 + conf.setAutoExecOffset(autoExecOffset);
  239 +
  240 + lineConfigData.set(conf);
  241 + rs.put("status", ResponseCode.SUCCESS);
  242 + rs.put("conf", conf);
  243 + } catch (Exception e) {
  244 + rs.put("status", ResponseCode.ERROR);
  245 + rs.put("msg", e.getMessage());
  246 + logger.error("", e);
  247 + }
  248 + return rs;
  249 + }
  250 +
  251 + @Override
  252 + public Map<String, Object> setReadReverse(int status, String lineCode) {
  253 + Map<String, Object> rs = new HashMap<>();
  254 + try {
  255 + LineConfig conf = lineConfigData.get(lineCode);
  256 + conf.setReadReverse(status==1?true:false);
  257 +
  258 + lineConfigData.set(conf);
  259 + rs.put("status", ResponseCode.SUCCESS);
  260 + rs.put("conf", conf);
  261 + } catch (Exception e) {
  262 + rs.put("status", ResponseCode.ERROR);
  263 + rs.put("msg", e.getMessage());
  264 + logger.error("", e);
  265 + }
  266 + return rs;
  267 + }
  268 +}
src/main/resources/static/real_control_v2/fragments/north/nav/line_config/fbzdzx_config.html
1 -<div id="nav-fbzdzx_config-modal" class="uk-modal">  
2 - <div class="uk-modal-dialog uk-modal-dialog-blank" style="overflow: hidden;">  
3 - <button class="uk-modal-close uk-close" type="button"></button>  
4 - <div class="uk-grid uk-flex-middle" data-uk-grid-margin>  
5 - <div class="uk-width-medium-1-6 uk-height-viewport line-config-tree" data-uk-observe>  
6 - <h3 class="title">翻班与自动完成</h3>  
7 - <div class="uk-accordion" data-uk-accordion="{showfirst:false}" ></div>  
8 - </div>  
9 - <div class="uk-width-medium-5-6 uk-height-viewport right-container" data-uk-observe>  
10 - <div id="fbzdzx_config_entity_panel"></div>  
11 - <div id="buffer_config_panel"></div>  
12 - </div>  
13 - </div>  
14 - </div>  
15 -  
16 -  
17 - <script id="nav-fbzdzx_config-modal-tree-temp" type="text/html">  
18 - {{each array as line i}}  
19 - <h3 class="uk-accordion-title" data-id="{{line.lineCode}}">{{line.name}}</h3>  
20 - <div class="uk-accordion-content">  
21 - <ul class="uk-list uk-list-line" id="smooth_scroll_list">  
22 - <li><a data-href="#schedule_reload_time_panel" >班次更新时间</a></li>  
23 - <li><a data-href="#schedule_auto_exec_panel" >班次自动执行</a></li>  
24 - </ul>  
25 - </div>  
26 - {{/each}}  
27 - </script>  
28 -  
29 - <script>  
30 - (function () {  
31 - var modal = '#nav-fbzdzx_config-modal',  
32 - lineConfig, activeCode;  
33 -  
34 - //初始化滚动条  
35 - $('.right-container', modal).perfectScrollbar({suppressScrollX: true});  
36 - /**  
37 - * 手风琴拨动  
38 - */  
39 - $('.uk-accordion').on('toggle.uk.accordion', function (e, active, toggle, content) {  
40 - if(active){  
41 - activeCode = $(toggle).data('id');  
42 - load();  
43 - }  
44 - });  
45 -  
46 - $(modal).on('init', function (e, data) {  
47 - e.stopPropagation();  
48 - var htmlStr = template('nav-fbzdzx_config-modal-tree-temp', {array: gb_data_basic.activeLines});  
49 - $('.line-config-tree .uk-accordion', modal).html(htmlStr);  
50 -  
51 - if(data.activeCode)  
52 - activeCode = data.activeCode;  
53 - else{  
54 - //展开tab激活的线路  
55 - var $activeTab = $('#main-tab-content>li.line_schedule.uk-active');  
56 - if($activeTab.length > 0)  
57 - activeCode = $activeTab.data('id');  
58 - else{  
59 - //展开第一个  
60 - var $first = $('.uk-accordion-title:eq(0)', modal);  
61 - activeCode = $first.data('id');  
62 - }  
63 - }  
64 -  
65 - setTimeout(function () {  
66 - $('.uk-accordion-title[data-id='+activeCode+']', modal).trigger('click');  
67 - }, 500);  
68 - });  
69 -  
70 -  
71 - var load = function () {  
72 - //获取线路配置信息  
73 - $.get('/lineConfig/getByLineCode', {lineCode: activeCode}, function (conf) {  
74 - lineConfig = conf;  
75 -  
76 - loadConfigEntity();  
77 - loadBufferConfig();  
78 -  
79 - setTimeout(function () {  
80 - //更新滚动条高度  
81 - $('.right-container', modal).perfectScrollbar('update');  
82 - }, 500);  
83 - });  
84 - };  
85 -  
86 - //线路配置表属性设置  
87 - var loadConfigEntity = function () {  
88 - $.get('/real_control_v2/fragments/north/nav/line_config/fbzdzx_config_entity.html', function (attrDom) {  
89 - $('.right-container #fbzdzx_config_entity_panel', modal)  
90 - .html(attrDom)  
91 - .find('#fbzdzx_config_entity_wrap')  
92 - .trigger('init', {lineConfig: lineConfig});  
93 - });  
94 - };  
95 -  
96 -  
97 - //瞄点  
98 - $(modal).on('click', '#smooth_scroll_list>li>a', function () {  
99 - var id = $(this).data('href');  
100 - scrollToElement($(id, modal));  
101 - });  
102 -  
103 - function scrollToElement(ele) {  
104 - var cont = $('.right-container', modal), diff = 10;  
105 - cont.animate({  
106 - scrollTop: ele.offset().top - cont.offset().top + cont.scrollTop() - diff  
107 - }, 300);  
108 - }  
109 - })();  
110 - </script>  
111 -</div> 1 +<div id="nav-fbzdzx_config-modal" class="uk-modal">
  2 + <div class="uk-modal-dialog uk-modal-dialog-blank" style="overflow: hidden;">
  3 + <button class="uk-modal-close uk-close" type="button"></button>
  4 + <div class="uk-grid uk-flex-middle" data-uk-grid-margin>
  5 + <div class="uk-width-medium-1-6 uk-height-viewport line-config-tree" data-uk-observe>
  6 + <h3 class="title">翻班与自动完成</h3>
  7 + <div class="uk-accordion" data-uk-accordion="{showfirst:false}" ></div>
  8 + </div>
  9 + <div class="uk-width-medium-5-6 uk-height-viewport right-container" data-uk-observe>
  10 + <div id="fbzdzx_config_entity_panel"></div>
  11 + <div id="buffer_config_panel"></div>
  12 + </div>
  13 + </div>
  14 + </div>
  15 +
  16 +
  17 + <script id="nav-fbzdzx_config-modal-tree-temp" type="text/html">
  18 + {{each array as line i}}
  19 + <h3 class="uk-accordion-title" data-id="{{line.lineCode}}">{{line.name}}</h3>
  20 + <div class="uk-accordion-content">
  21 + <ul class="uk-list uk-list-line" id="smooth_scroll_list">
  22 + <li><a data-href="#schedule_reload_time_panel" >班次更新时间</a></li>
  23 + <li><a data-href="#schedule_auto_exec_panel" >班次自动执行</a></li>
  24 + </ul>
  25 + </div>
  26 + {{/each}}
  27 + </script>
  28 +
  29 + <script>
  30 + (function () {
  31 + var modal = '#nav-fbzdzx_config-modal',
  32 + lineConfig, activeCode;
  33 +
  34 + //初始化滚动条
  35 + $('.right-container', modal).perfectScrollbar({suppressScrollX: true});
  36 + /**
  37 + * 手风琴拨动
  38 + */
  39 + $('.uk-accordion').on('toggle.uk.accordion', function (e, active, toggle, content) {
  40 + if(active){
  41 + activeCode = $(toggle).data('id');
  42 + load();
  43 + }
  44 + });
  45 +
  46 + $(modal).on('init', function (e, data) {
  47 + e.stopPropagation();
  48 + var htmlStr = template('nav-fbzdzx_config-modal-tree-temp', {array: gb_data_basic.activeLines});
  49 + $('.line-config-tree .uk-accordion', modal).html(htmlStr);
  50 +
  51 + if(data.activeCode)
  52 + activeCode = data.activeCode;
  53 + else{
  54 + //展开tab激活的线路
  55 + var $activeTab = $('#main-tab-content>li.line_schedule.uk-active');
  56 + if($activeTab.length > 0)
  57 + activeCode = $activeTab.data('id');
  58 + else{
  59 + //展开第一个
  60 + var $first = $('.uk-accordion-title:eq(0)', modal);
  61 + activeCode = $first.data('id');
  62 + }
  63 + }
  64 +
  65 + setTimeout(function () {
  66 + $('.uk-accordion-title[data-id='+activeCode+']', modal).trigger('click');
  67 + }, 500);
  68 + });
  69 +
  70 +
  71 + var load = function () {
  72 + //获取线路配置信息
  73 + $.get('/lineConfig/getByLineCode', {lineCode: activeCode}, function (conf) {
  74 + lineConfig = conf;
  75 +
  76 + loadConfigEntity();
  77 +
  78 + setTimeout(function () {
  79 + //更新滚动条高度
  80 + $('.right-container', modal).perfectScrollbar('update');
  81 + }, 500);
  82 + });
  83 + };
  84 +
  85 + //线路配置表属性设置
  86 + var loadConfigEntity = function () {
  87 + $.get('/real_control_v2/fragments/north/nav/line_config/fbzdzx_config_entity.html', function (attrDom) {
  88 + $('.right-container #fbzdzx_config_entity_panel', modal)
  89 + .html(attrDom)
  90 + .find('#fbzdzx_config_entity_wrap')
  91 + .trigger('init', {lineConfig: lineConfig});
  92 + });
  93 + };
  94 +
  95 +
  96 + //瞄点
  97 + $(modal).on('click', '#smooth_scroll_list>li>a', function () {
  98 + var id = $(this).data('href');
  99 + scrollToElement($(id, modal));
  100 + });
  101 +
  102 + function scrollToElement(ele) {
  103 + var cont = $('.right-container', modal), diff = 10;
  104 + cont.animate({
  105 + scrollTop: ele.offset().top - cont.offset().top + cont.scrollTop() - diff
  106 + }, 300);
  107 + }
  108 + })();
  109 + </script>
  110 +</div>
src/main/resources/static/real_control_v2/fragments/north/nav/line_config/fbzdzx_config_entity.html
1 -<!-- 线路配置表相关属性 -->  
2 -<div id="fbzdzx_config_entity_wrap">  
3 - <form class="uk-form"></form>  
4 -  
5 - <script id="fbzdzx_config_entity_form-temp" type="text/html">  
6 - <div id="schedule_reload_time_panel">  
7 - <h2 class="btn_title_line">  
8 - <a class="uk-link-reset">班次更新时间</a>  
9 - </h2>  
10 - <div>  
11 - <div>  
12 - <span class="line_name"></span>每天  
13 - <div class="uk-form-icon" style="margin: 0 5px;">  
14 - <i class="uk-icon-clock-o"></i>  
15 - <input name="startOptInput" readonly type="text" class="z-depth-input" value="{{startOpt}}"  
16 - style="width: 151px;"  
17 - data-uk-timepicker>  
18 - </div>  
19 - 更新到当日排班  
20 - </div>  
21 - <ul class="uk-list">  
22 - <li>  
23 - <small><i class="uk-icon-question-circle"></i> 所有发车时间小于该时间的班次都默认跨过24点,手动调整的实发实达均应用此规则。</small>  
24 - </li>  
25 - </ul>  
26 - <button class="uk-button uk-button-mini" id="clearRealScheduleBtn">删除实际排班</button>  
27 - <button class="uk-button uk-button-mini" id="reLoadRealScheduleBtn">重新加载实际排班</button>  
28 - <button class="uk-button uk-button-mini" disabled>加载历史GPS恢复到离站</button>  
29 - </div>  
30 - </div>  
31 -  
32 - <div id="schedule_auto_exec_panel">  
33 - <h2 class="btn_title_line">  
34 - <a class="uk-link-reset">班次自动执行</a>  
35 - </h2>  
36 - <div>  
37 - <div>  
38 - <label>  
39 - <input type="checkbox" id="enableAutoExec" {{autoExec?"checked":""}}> 启用自动班次执行  
40 - </label>  
41 - </div>  
42 - <ul class="uk-list">  
43 - <li>  
44 - <small style="color: red;font-size: 14px;">1、 你必须只应该对【无固定走向且无人监管的线路】启用此项。</small>  
45 - </li>  
46 - <li>  
47 - <small>2、启用该选项后,系统将不再依赖相关定位信号来执行班次。</small>  
48 - </li>  
49 - <li>  
50 - <small>3、系统将在合适的时候自动填入实发实达时间,以完善报表。</small>  
51 - </li>  
52 - <li>  
53 - <small>4、系统不会下发班次调度指令。</small>  
54 - </li>  
55 - </ul>  
56 - </div>  
57 - </div>  
58 -  
59 - </script>  
60 -  
61 - <script>  
62 - (function () {  
63 -  
64 - var wrap = '#fbzdzx_config_entity_wrap', conf, parks, upStationRoutes;  
65 -  
66 - /**  
67 - * 删除实际排班  
68 - */  
69 - var clearRealSchedule = function (e) {  
70 - e.stopPropagation();  
71 - var lineCode = conf.line.lineCode;  
72 - var htmlStr = '<h4 style="color: red;">你确定要删除【' + conf.line.name + '】今日的实际排班?</h4><h5 style="margin-top: 15px;">今日的实际排班会被删除</h5><h5 style="margin-top: 15px;">人车、路牌、待发等相关班次调整信息会被删除。</h5><h5 style="margin-top: 15px;">调度指令和期间与设备的通讯记录被保留</h5><h5 style="margin-top: 15px;">后台日志中的人工操作痕迹被保留</h5>';  
73 - alt_confirm(htmlStr, function () {  
74 - show_wait_modal('正在清除数据...');  
75 - gb_common.$post('/realSchedule/deleteRealSchedule', {lineCode: lineCode}, function () {  
76 - //刷新班次表格  
77 - gb_schedule_table.reLoadAndRefresh(lineCode);  
78 - hide_wait_modal();  
79 - notify_succ('删除班次成功!!!');  
80 - });  
81 - }, '确认删除' + conf.line.name + '的实际排班', true);  
82 -  
83 - return false;  
84 - };  
85 -  
86 - /**  
87 - * 重新载入实际排班  
88 - */  
89 - var reLoadRealSchedule = function (e) {  
90 - e.stopPropagation();  
91 - var lineCode = conf.line.lineCode;  
92 - show_wait_modal('正在重载数据...');  
93 - gb_common.$post('/realSchedule/reLoadRealSchedule', {lineCode: lineCode}, function () {  
94 - //刷新班次表格  
95 - gb_schedule_table.reLoadAndRefresh(lineCode);  
96 - hide_wait_modal();  
97 - notify_succ('重新载入班次成功');  
98 - });  
99 - return false;  
100 - };  
101 -  
102 - $(wrap).on('init', function (e, data) {  
103 - e.stopPropagation();  
104 - conf = data.lineConfig;  
105 - //停车场  
106 - $.get('/basic/parks', function (rs) {  
107 - parks = [];  
108 - for (var code in rs) {  
109 - parks.push({code: code, name: rs[code]});  
110 - }  
111 -  
112 - parks.sort(function (a, b) {  
113 - return $.trim(a.name).localeCompare($.trim(b.name), 'zh-CN');  
114 - });  
115 - renderPSDom();  
116 - });  
117 - //上行站点路由  
118 - upStationRoutes = gb_common.groupBy(gb_data_basic.stationRoutes(conf.line.lineCode).sort(function (a, b) {  
119 - return a.stationRouteCode - b.stationRouteCode;  
120 - }), 'directions')[0];  
121 -  
122 - var htmlStr = template('fbzdzx_config_entity_form-temp', conf);  
123 - $('form', wrap).html(htmlStr);  
124 -  
125 - $('.line_name', '#fbzdzx_config_entity_wrap').text(conf.line.name);  
126 - //更新排班时间  
127 - $('input[name=startOptInput]', wrap).on('change', updateStartTime);  
128 - //出场时间类型  
129 - $('select[name=outParkTypeSelect]', wrap).on('change', updateOutParkType);  
130 - //原线路回场  
131 - $('select[name=inParkForSourceSelect]', wrap).on('change', enableInParkForSource);  
132 - //删除班次  
133 - $('#clearRealScheduleBtn', wrap).on('click', clearRealSchedule);  
134 - //重新载入实际排班  
135 - $('#reLoadRealScheduleBtn', wrap).on('click', reLoadRealSchedule);  
136 - $('#enableAutoExec', wrap).on('click', autoExecFun);  
137 - });  
138 -  
139 - function changeTwinsParkAndStation() {  
140 - var parks='',stations=''  
141 - ,$panel = $('.park-and-station-wrap', wrap);  
142 -  
143 - $('select[name=twinsPark]', $panel).each(function () {  
144 - parks += ($(this).val() + ',');  
145 - });  
146 -  
147 - $('select[name=twinsStation]', $panel).each(function () {  
148 - stations += ($(this).val() + ',');  
149 - });  
150 -  
151 - if(parks.length > 0)  
152 - parks = parks.substr(0, parks.length - 1);  
153 - if(stations.length > 0)  
154 - stations = stations.substr(0, stations.length - 1);  
155 -  
156 - gb_common.$post('/lineConfig/parkAndStationSet', {  
157 - lineCode: conf.line.lineCode,  
158 - twinsPark: parks,  
159 - twinsStation: stations  
160 - }, function (rs) {  
161 - notify_succ('已保存!!');  
162 - conf = rs.conf;  
163 - });  
164 - }  
165 -  
166 - //更新排班时间  
167 - var startOptFlag;  
168 -  
169 - function updateStartTime() {  
170 - if (startOptFlag || $(this).val() == conf.startOpt)  
171 - return;  
172 - startOptFlag = true;  
173 - var that = this;  
174 - setTimeout(function () {  
175 - var timeStr = $(that).val();  
176 - gb_common.$post('/lineConfig/editTime', {  
177 - lineCode: conf.line.lineCode,  
178 - time: timeStr  
179 - }, function (rs) {  
180 - notify_succ('班次更新时间调整为 ' + timeStr);  
181 - conf.startOpt = rs.time;  
182 - });  
183 - startOptFlag = false;  
184 - }, 300);  
185 - }  
186 -  
187 - function updateOutParkType() {  
188 - var type = $(this).val();  
189 - var lineCode = conf.line.lineCode;  
190 -  
191 - var data = {lineCode: lineCode, type: type, parkCode: '', stationCode: ''};  
192 - //出站既是出场  
193 - if (type == 2) {  
194 - //如果配置上有信息  
195 - if(conf.twinsParks){  
196 - data.parkCode = conf.twinsParks;  
197 - data.stationCode = conf.twinsStations;  
198 - }  
199 - else{  
200 - data.parkCode = gb_data_basic.getLineInformation(lineCode).carPark;//默认关联 线路标准停车场  
201 - data.stationCode = upStationRoutes[0].stationCode;//和上行起点站  
202 - }  
203 - }  
204 - gb_common.$post('/lineConfig/editOutTimeType', data, function (rs) {  
205 - notify_succ('调整出场时间类型成功!');  
206 - conf = rs.conf;  
207 -  
208 - //渲染场站关联dom  
209 - renderPSDom();  
210 - });  
211 - }  
212 -  
213 -  
214 -  
215 - function enableInParkForSource() {  
216 - var enable = $(this).val();  
217 - gb_common.$post('/lineConfig/enableInParkForSource', {  
218 - lineCode: conf.line.lineCode,  
219 - enable: enable  
220 - }, function () {  
221 - notify_succ((enable == 1 ? '启用' : '禁用') + '原线路回场');  
222 - conf.inParkForSource = enable;  
223 - });  
224 - }  
225 -  
226 -  
227 - /**  
228 - * 自动执行  
229 - */  
230 - function autoExecFun(){  
231 - var that = this;  
232 - if(that.checked){  
233 - that.checked = false;  
234 - alt_confirm('<span style="color: red;font-size: 16px;">启用【' + conf.line.name + '】的自动执行功能?</span>', function () {  
235 - var data = {  
236 - lineCode: conf.line.lineCode,  
237 - autoExec: true  
238 - };  
239 - gb_common.$post('/lineConfig/setAutoExec', data, function (rs) {  
240 - notify_succ('启用成功!');  
241 - conf = rs.conf;  
242 -  
243 - that.checked = true;  
244 - });  
245 - }, '我确定要将【' + conf.line.name + '】设置为自动执行', true);  
246 - }  
247 - else{  
248 - that.checked = true;  
249 - alt_confirm('<span style="color: red;font-size: 16px;">禁用【' + conf.line.name + '】的自动执行功能?</span>', function () {  
250 - var data = {  
251 - lineCode: conf.line.lineCode,  
252 - autoExec: false  
253 - };  
254 - gb_common.$post('/lineConfig/setAutoExec', data, function (rs) {  
255 - notify_succ('禁用成功!');  
256 - conf = rs.conf;  
257 -  
258 - that.checked = false;  
259 - });  
260 - }, '我确定要禁用【' + conf.line.name + '】的自动执行', true);  
261 - }  
262 - }  
263 -  
264 -  
265 - /**  
266 - * 删除 场既是站 项目  
267 - */  
268 - $(wrap).on('click', '.c_2_s_list .item .uk-close', function () {  
269 - $(this).parents('.item').remove();  
270 - changeTwinsParkAndStation();  
271 - });  
272 -  
273 -  
274 - $(wrap).on('change', 'select[name=twinsPark]', changeTwinsParkAndStation);  
275 - $(wrap).on('change', 'select[name=twinsStation]', changeTwinsParkAndStation);  
276 - })();  
277 - </script> 1 +<!-- 线路配置表相关属性 -->
  2 +<div id="fbzdzx_config_entity_wrap">
  3 + <form class="uk-form"></form>
  4 +
  5 + <script id="fbzdzx_config_entity_form-temp" type="text/html">
  6 + <div id="schedule_reload_time_panel">
  7 + <h2 class="btn_title_line">
  8 + <a class="uk-link-reset">班次更新时间</a>
  9 + </h2>
  10 + <div>
  11 + <div>
  12 + <span class="line_name"></span>每天
  13 + <div class="uk-form-icon" style="margin: 0 5px;">
  14 + <i class="uk-icon-clock-o"></i>
  15 + <input name="startOptInput" readonly type="text" class="z-depth-input" value="{{startOpt}}"
  16 + style="width: 151px;"
  17 + data-uk-timepicker>
  18 + </div>
  19 + 更新到当日排班
  20 + </div>
  21 + <ul class="uk-list">
  22 + <li>
  23 + <small><i class="uk-icon-question-circle"></i> 所有发车时间小于该时间的班次都默认跨过24点,手动调整的实发实达均应用此规则。</small>
  24 + </li>
  25 + </ul>
  26 + <button class="uk-button uk-button-mini" id="clearRealScheduleBtn">删除实际排班</button>
  27 + <button class="uk-button uk-button-mini" id="reLoadRealScheduleBtn">重新加载实际排班</button>
  28 + <button class="uk-button uk-button-mini" disabled>加载历史GPS恢复到离站</button>
  29 + </div>
  30 + </div>
  31 +
  32 + <div id="schedule_auto_exec_panel">
  33 + <h2 class="btn_title_line">
  34 + <a class="uk-link-reset">班次自动执行</a>
  35 + </h2>
  36 + <div>
  37 + <table>
  38 + <tr>
  39 + <td>
  40 + <label>
  41 + <input type="checkbox" id="enableAutoExec" {{autoExec?"checked":""}}> 启用自动班次执行
  42 + </label>
  43 + </td>
  44 + </tr>
  45 + <tr>
  46 + <td>
  47 + 自动执行偏移
  48 + &nbsp;<input type="number" value="{{autoExecOffset}}" id="autoExecOffset" name="autoExecOffset" style="width: 100px;" {{if !autoExec}}readonly{{/if}}>&nbsp;分钟
  49 + </td>
  50 + </tr>
  51 + </table>
  52 + <ul class="uk-list">
  53 + <li>
  54 + <small style="color: red;font-size: 14px;">1、 你必须只应该对【无固定走向且无人监管的线路】启用此项。</small>
  55 + </li>
  56 + <li>
  57 + <small>2、启用该选项后,系统将不再依赖相关定位信号来执行班次。</small>
  58 + </li>
  59 + <li>
  60 + <small>3、系统将在合适的时候自动填入实发实达时间,以完善报表。</small>
  61 + </li>
  62 + <li>
  63 + <small>4、自动执行偏移为0时按1-3执行,自动执行偏移>0时按5-7执行。</small>
  64 + </li>
  65 + <li>
  66 + <small>5、捕捉的GPS信号在计划发车、计划到达的前后偏移时间内,则自动填入。</small>
  67 + </li>
  68 + <li>
  69 + <small>6、当前时间超过到达时间达到偏移时间,则跳过当前班次,执行下一个班次。</small>
  70 + </li>
  71 + <li>
  72 + <small>7、对于存在实际发车时间或实际到达时间缺失的,将在收班后的合适时间根据当天GPS重新进行计算。</small>
  73 + </li>
  74 + </ul>
  75 + </div>
  76 + </div>
  77 +
  78 + </script>
  79 +
  80 + <script>
  81 + $(function () {
  82 +
  83 + var wrap = '#fbzdzx_config_entity_wrap', conf, parks, upStationRoutes;
  84 +
  85 + /**
  86 + * 删除实际排班
  87 + */
  88 + var clearRealSchedule = function (e) {
  89 + e.stopPropagation();
  90 + var lineCode = conf.line.lineCode;
  91 + var htmlStr = '<h4 style="color: red;">你确定要删除【' + conf.line.name + '】今日的实际排班?</h4><h5 style="margin-top: 15px;">今日的实际排班会被删除</h5><h5 style="margin-top: 15px;">人车、路牌、待发等相关班次调整信息会被删除。</h5><h5 style="margin-top: 15px;">调度指令和期间与设备的通讯记录被保留</h5><h5 style="margin-top: 15px;">后台日志中的人工操作痕迹被保留</h5>';
  92 + alt_confirm(htmlStr, function () {
  93 + show_wait_modal('正在清除数据...');
  94 + gb_common.$post('/realSchedule/deleteRealSchedule', {lineCode: lineCode}, function () {
  95 + //刷新班次表格
  96 + gb_schedule_table.reLoadAndRefresh(lineCode);
  97 + hide_wait_modal();
  98 + notify_succ('删除班次成功!!!');
  99 + });
  100 + }, '确认删除' + conf.line.name + '的实际排班', true);
  101 +
  102 + return false;
  103 + };
  104 +
  105 + /**
  106 + * 重新载入实际排班
  107 + */
  108 + var reLoadRealSchedule = function (e) {
  109 + e.stopPropagation();
  110 + var lineCode = conf.line.lineCode;
  111 + show_wait_modal('正在重载数据...');
  112 + gb_common.$post('/realSchedule/reLoadRealSchedule', {lineCode: lineCode}, function () {
  113 + //刷新班次表格
  114 + gb_schedule_table.reLoadAndRefresh(lineCode);
  115 + hide_wait_modal();
  116 + notify_succ('重新载入班次成功');
  117 + });
  118 + return false;
  119 + };
  120 +
  121 + $(wrap).on('init', function (e, data) {
  122 + e.stopPropagation();
  123 + conf = data.lineConfig;
  124 + //停车场
  125 + $.get('/basic/parks', function (rs) {
  126 + parks = [];
  127 + for (var code in rs) {
  128 + parks.push({code: code, name: rs[code]});
  129 + }
  130 +
  131 + parks.sort(function (a, b) {
  132 + return $.trim(a.name).localeCompare($.trim(b.name), 'zh-CN');
  133 + });
  134 + });
  135 + //上行站点路由
  136 + upStationRoutes = gb_common.groupBy(gb_data_basic.stationRoutes(conf.line.lineCode).sort(function (a, b) {
  137 + return a.stationRouteCode - b.stationRouteCode;
  138 + }), 'directions')[0];
  139 +
  140 + var htmlStr = template('fbzdzx_config_entity_form-temp', conf);
  141 + $('form', wrap).html(htmlStr);
  142 +
  143 + $('.line_name', '#fbzdzx_config_entity_wrap').text(conf.line.name);
  144 + //更新排班时间
  145 + $('input[name=startOptInput]', wrap).on('change', updateStartTime);
  146 + //出场时间类型
  147 + $('select[name=outParkTypeSelect]', wrap).on('change', updateOutParkType);
  148 + //原线路回场
  149 + $('select[name=inParkForSourceSelect]', wrap).on('change', enableInParkForSource);
  150 + //删除班次
  151 + $('#clearRealScheduleBtn', wrap).on('click', clearRealSchedule);
  152 + //重新载入实际排班
  153 + $('#reLoadRealScheduleBtn', wrap).on('click', reLoadRealSchedule);
  154 + $('#enableAutoExec', wrap).on('click', autoExecFun);
  155 + $('#autoExecOffset').on('change', autoExecOffsetFun)
  156 + });
  157 +
  158 + //更新排班时间
  159 + var startOptFlag;
  160 +
  161 + function updateStartTime() {
  162 + if (startOptFlag || $(this).val() == conf.startOpt)
  163 + return;
  164 + startOptFlag = true;
  165 + var that = this;
  166 + setTimeout(function () {
  167 + var timeStr = $(that).val();
  168 + gb_common.$post('/lineConfig/editTime', {
  169 + lineCode: conf.line.lineCode,
  170 + time: timeStr
  171 + }, function (rs) {
  172 + notify_succ('班次更新时间调整为 ' + timeStr);
  173 + conf.startOpt = rs.time;
  174 + });
  175 + startOptFlag = false;
  176 + }, 300);
  177 + }
  178 +
  179 + function updateOutParkType() {
  180 + var type = $(this).val();
  181 + var lineCode = conf.line.lineCode;
  182 +
  183 + var data = {lineCode: lineCode, type: type, parkCode: '', stationCode: ''};
  184 + //出站既是出场
  185 + if (type == 2) {
  186 + //如果配置上有信息
  187 + if(conf.twinsParks){
  188 + data.parkCode = conf.twinsParks;
  189 + data.stationCode = conf.twinsStations;
  190 + }
  191 + else{
  192 + data.parkCode = gb_data_basic.getLineInformation(lineCode).carPark;//默认关联 线路标准停车场
  193 + data.stationCode = upStationRoutes[0].stationCode;//和上行起点站
  194 + }
  195 + }
  196 + gb_common.$post('/lineConfig/editOutTimeType', data, function (rs) {
  197 + notify_succ('调整出场时间类型成功!');
  198 + conf = rs.conf;
  199 +
  200 + //渲染场站关联dom
  201 + renderPSDom();
  202 + });
  203 + }
  204 +
  205 +
  206 +
  207 + function enableInParkForSource() {
  208 + var enable = $(this).val();
  209 + gb_common.$post('/lineConfig/enableInParkForSource', {
  210 + lineCode: conf.line.lineCode,
  211 + enable: enable
  212 + }, function () {
  213 + notify_succ((enable == 1 ? '启用' : '禁用') + '原线路回场');
  214 + conf.inParkForSource = enable;
  215 + });
  216 + }
  217 +
  218 +
  219 + /**
  220 + * 自动执行
  221 + */
  222 + function autoExecFun(){
  223 + var that = this, autoExecOffset = $('#autoExecOffset').val();
  224 + if(that.checked){
  225 + that.checked = false;
  226 + alt_confirm('<span style="color: red;font-size: 16px;">启用【' + conf.line.name + '】的自动执行功能?</span>', function () {
  227 + var data = {
  228 + lineCode: conf.line.lineCode,
  229 + autoExec: true,
  230 + autoExecOffset: autoExecOffset
  231 + };
  232 + gb_common.$post('/lineConfig/setAutoExec', data, function (rs) {
  233 + notify_succ('启用成功!');
  234 + conf = rs.conf;
  235 +
  236 + that.checked = true;
  237 + $('#autoExecOffset').attr('readonly', false);
  238 + });
  239 + }, '我确定要将【' + conf.line.name + '】设置为自动执行', true);
  240 + }
  241 + else{
  242 + that.checked = true;
  243 + alt_confirm('<span style="color: red;font-size: 16px;">禁用【' + conf.line.name + '】的自动执行功能?</span>', function () {
  244 + var data = {
  245 + lineCode: conf.line.lineCode,
  246 + autoExec: false,
  247 + autoExecOffset: autoExecOffset
  248 + };
  249 + gb_common.$post('/lineConfig/setAutoExec', data, function (rs) {
  250 + notify_succ('禁用成功!');
  251 + conf = rs.conf;
  252 +
  253 + that.checked = false;
  254 + $('#autoExecOffset').attr('readonly', true);
  255 + });
  256 + }, '我确定要禁用【' + conf.line.name + '】的自动执行', true);
  257 + }
  258 + }
  259 +
  260 + // 自动执行偏移
  261 + function autoExecOffsetFun() {
  262 + var checked = $('#enableAutoExec').attr('checked'), autoExecOffset = $(this).val();
  263 + if (!autoExecOffset) {
  264 + $(this).val(0);
  265 + }
  266 + if (checked == 'checked') {
  267 + var data = {
  268 + lineCode: conf.line.lineCode,
  269 + autoExec: true,
  270 + autoExecOffset: autoExecOffset
  271 + };
  272 + gb_common.$post('/lineConfig/setAutoExec', data, function (rs) {
  273 + notify_succ('设置成功!');
  274 + conf = rs.conf;
  275 + });
  276 + }
  277 + }
  278 + });
  279 + </script>
278 </div> 280 </div>
279 \ No newline at end of file 281 \ No newline at end of file