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 151 /** 线调业务 */
152 152 sexec.scheduleWithFixedDelay(scheduleRefreshThread, 10, 120, TimeUnit.SECONDS);//班次更新线程
153 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 155 //sexec.scheduleWithFixedDelay(rfidDataLoader, 5, 5, TimeUnit.SECONDS);//抓取RFID数据
156 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 30 }
31 31  
32 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 37 public static String getUrlHttpDirective() {
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/InStationProcess.java
... ... @@ -51,7 +51,7 @@ public class InStationProcess {
51 51 public void process(GpsEntity gps) {
52 52 //自动执行的班次信号,滚蛋
53 53 LineConfig config = lineConfigData.get(gps.getLineId());
54   - if (null != config && config.isAutoExec())
  54 + if (null != config && config.isAutoExec() && config.getAutoExecOffset() == 0)
55 55 return;
56 56  
57 57 GpsEntity prev = GpsCacheData.getPrev(gps);
... ... @@ -139,6 +139,12 @@ public class InStationProcess {
139 139 */
140 140 private void inEndStation(ScheduleRealInfo sch, GpsEntity gps) {
141 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 149 if (!validInPremise(gps) && isNormalSch(sch))
144 150 return;
... ...
src/main/java/com/bsth/data/gpsdata_v2/handlers/OutStationProcess.java
... ... @@ -46,7 +46,7 @@ public class OutStationProcess {
46 46 public void process(GpsEntity gps) {
47 47 //自动执行的线路,滚蛋
48 48 LineConfig config = lineConfigData.get(gps.getLineId());
49   - if (null != config && config.isAutoExec())
  49 + if (null != config && config.isAutoExec() && config.getAutoExecOffset() == 0)
50 50 return;
51 51  
52 52 GpsEntity prev = GpsCacheData.getPrev(gps);
... ... @@ -86,6 +86,13 @@ public class OutStationProcess {
86 86 ((sch.getQdzCode().equals(prev.getStopNo())
87 87 && (gps.getInstation() == 0 || !gps.getStopNo().equals(prev.getStopNo())))
88 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 97 if (!signalSchPlanMatcher.outMatch(gps, sch)) {
91 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 import org.springframework.beans.factory.annotation.Autowired;
10 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 37 //要自动执行的线路
40 38 List<String> autos = new ArrayList<>();
41 39 Collection<LineConfig> lcs = lineConfigData.getAll();
  40 + Map<String, LineConfig> line2config = new HashMap<>();
42 41  
43 42 for(LineConfig config : lcs){
44 43 if(config.isAutoExec()){
  44 + line2config.put(config.getLine().getLineCode(), config);
45 45 autos.add(config.getLine().getLineCode());
46 46 }
47 47 }
... ... @@ -51,7 +51,14 @@ public class AutoExecScanThread extends Thread{
51 51 List<ScheduleRealInfo> all = new ArrayList<>(dayOfSchedule.findAll());
52 52 for(ScheduleRealInfo sch : all){
53 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 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 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 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 248 public String getTwinsParks() {
236 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 280 </div>
279 281 \ No newline at end of file
... ...