Commit 4db4b302e8865fad7662a2a6dc3993c26b65e188

Authored by 王通
1 parent d466e911

1.RFID状态逻辑变更,加入RFID状态图例

src/main/java/com/bsth/data/gpsdata_v2/rfid/handle/RfidDataHandler.java
... ... @@ -33,7 +33,7 @@ public class RfidDataHandler {
33 33  
34 34 private final static Logger logger = LoggerFactory.getLogger(RfidDataHandler.class);
35 35  
36   - private Map<String, RfidInfo> nbbm2rfid = new ConcurrentHashMap<>();
  36 + private static Map<String, RfidInfo> nbbm2rfid = new ConcurrentHashMap<>();
37 37  
38 38 /**
39 39 *
... ... @@ -55,17 +55,18 @@ public class RfidDataHandler {
55 55 if (ri.getEmployeeCard() != null) {
56 56 state |= 2;
57 57 }
58   - if (scheduleRealInfo.getRfidState() != state) {
59   - if ((state & 1) == 1) {
60   - System.out.println("aaa");
61   - }
  58 + if (scheduleRealInfo.getRfidState() < state) {
62 59 scheduleRealInfo.setRfidState(state);
63 60 sendUtils.sendRfid(scheduleRealInfo);
64 61 }
65 62 }
66 63 }
67 64  
68   - checkValid();
  65 + //checkValid();
  66 + }
  67 +
  68 + public static void resetRfid(String nbbm) {
  69 + nbbm2rfid.remove(nbbm);
69 70 }
70 71  
71 72 /**
... ...
src/main/java/com/bsth/data/schedule/DayOfSchedule.java
1   -package com.bsth.data.schedule;
2   -
3   -import com.alibaba.fastjson.JSON;
4   -import com.alibaba.fastjson.JSONArray;
5   -import com.bsth.common.Constants;
6   -import com.bsth.common.ResponseCode;
7   -import com.bsth.data.LineConfigData;
8   -import com.bsth.data.gpsdata_v2.GpsRealData;
9   -import com.bsth.data.gpsdata_v2.utils.GpsDataRecovery;
10   -import com.bsth.data.schedule.f_a_l.FirstAndLastHandler;
11   -import com.bsth.entity.realcontrol.LineConfig;
12   -import com.bsth.entity.realcontrol.ScheduleRealInfo;
13   -import com.bsth.entity.report.RepairReport;
14   -import com.bsth.entity.schedule.SchedulePlanInfo;
15   -import com.bsth.repository.realcontrol.ScheduleRealInfoRepository;
16   -import com.bsth.service.schedule.SchedulePlanInfoService;
17   -import com.bsth.websocket.handler.SendUtils;
18   -import com.google.common.collect.ArrayListMultimap;
19   -import com.google.common.collect.HashMultimap;
20   -import com.google.common.collect.ListMultimap;
21   -import com.google.common.collect.Multimaps;
22   -import org.apache.commons.lang3.StringUtils;
23   -import org.joda.time.format.DateTimeFormat;
24   -import org.joda.time.format.DateTimeFormatter;
25   -import org.slf4j.Logger;
26   -import org.slf4j.LoggerFactory;
27   -import org.springframework.beans.factory.annotation.Autowired;
28   -import org.springframework.dao.DataIntegrityViolationException;
29   -import org.springframework.jdbc.core.BatchPreparedStatementSetter;
30   -import org.springframework.jdbc.core.JdbcTemplate;
31   -import org.springframework.jdbc.datasource.DataSourceTransactionManager;
32   -import org.springframework.stereotype.Component;
33   -import org.springframework.transaction.TransactionDefinition;
34   -import org.springframework.transaction.TransactionStatus;
35   -import org.springframework.transaction.support.DefaultTransactionDefinition;
36   -
37   -import java.sql.PreparedStatement;
38   -import java.sql.SQLException;
39   -import java.text.ParseException;
40   -import java.text.SimpleDateFormat;
41   -import java.util.*;
42   -import java.util.concurrent.ConcurrentHashMap;
43   -import java.util.concurrent.ConcurrentLinkedQueue;
44   -import java.util.concurrent.ConcurrentMap;
45   -
46   -/**
47   - * @author PanZhao
48   - * @ClassName: DayOfSchedule
49   - * @Description: TODO(当日实际排班)
50   - * @date 2016年8月15日 上午10:16:12
51   - */
52   -@Component
53   -public class DayOfSchedule {
54   -
55   - Logger logger = LoggerFactory.getLogger(this.getClass());
56   -
57   - //按线路分组的 “原始计划” 排班数据
58   - public static Map<String, List<SchedulePlanInfo>> schedulePlanMap;
59   -
60   - // 按车辆索引的班次数据
61   - private static ListMultimap<String, ScheduleRealInfo> nbbmScheduleMap;
62   -
63   - // 按营运公司索引的班次数据
64   - private static ListMultimap<String, ScheduleRealInfo> gsBmScheduleMap;
65   -
66   - //按线路索引计划用车
67   - private static HashMultimap<String, String> lineNbbmsMap;
68   -
69   - //按路牌索引班次数据 线路编码_路牌名称 ——> 班次list
70   - private static ArrayListMultimap<String, ScheduleRealInfo> lpScheduleMap;
71   -
72   - // 班次主键映射
73   - private static ConcurrentMap<Long, ScheduleRealInfo> id2SchedulMap;
74   -
75   - //车辆 ——> 当前执行班次
76   - private static ConcurrentMap<String, ScheduleRealInfo> carExecutePlanMap;
77   -
78   - // 持久化
79   - public static ConcurrentLinkedQueue<ScheduleRealInfo> pstBuffer;
80   -
81   - // 排序器
82   - private static ScheduleComparator.FCSJ schFCSJComparator;
83   -
84   - private static ScheduleComparator.DFSJ schDFSJComparator;
85   -
86   - private static Long sch_max_id=-1L;
87   -
88   - private Map<String, RepairReport> incode2report = new ConcurrentHashMap<String, RepairReport>();
89   -
90   - @Autowired
91   - LineConfigData lineConfigData;
92   -
93   - @Autowired
94   - ScheduleRealInfoRepository schRepository;
95   -
96   - @Autowired
97   - SchedulePlanInfoService schPlanService;
98   -
99   - @Autowired
100   - SchAttrCalculator schAttrCalculator;
101   -
102   - @Autowired
103   - SendUtils sendUtils;
104   -
105   - @Autowired
106   - GpsRealData gpsRealData;
107   -
108   - /**
109   - * 线路当前使用的排班的日期
110   - */
111   - public static Map<String, String> currSchDateMap;
112   -
113   - static {
114   - nbbmScheduleMap = ArrayListMultimap.create();
115   - nbbmScheduleMap = Multimaps.synchronizedListMultimap(nbbmScheduleMap);
116   -
117   - gsBmScheduleMap = ArrayListMultimap.create();
118   - lpScheduleMap = ArrayListMultimap.create();
119   - lineNbbmsMap = HashMultimap.create();
120   -
121   - id2SchedulMap = new ConcurrentHashMap<>();
122   - pstBuffer = new ConcurrentLinkedQueue<>();
123   - schFCSJComparator = new ScheduleComparator.FCSJ();
124   - schDFSJComparator = new ScheduleComparator.DFSJ();
125   - currSchDateMap = new HashMap<>();
126   - carExecutePlanMap = new ConcurrentHashMap<>();
127   -
128   - schedulePlanMap = new HashMap<>();
129   - }
130   -
131   - @Autowired
132   - LineConfigData lineConfigs;
133   -
134   - @Autowired
135   - GpsDataRecovery gpsDataRecovery;
136   -
137   - private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd"), fmtHHmm = DateTimeFormat.forPattern("HH:mm");
138   -
139   - //数据恢复
140   - public void dataRecovery() {
141   - Collection<LineConfig> confs = lineConfigs.getAll();
142   - String lineCode, currSchDate;
143   - for (LineConfig conf : confs) {
144   - lineCode = conf.getLine().getLineCode();
145   - currSchDate = calcSchDate(lineCode);
146   - //加载班次数据
147   - reloadSch(lineCode, currSchDate, false);
148   - }
149   -
150   - //恢复gps数据
151   - gpsDataRecovery.recovery();
152   - }
153   -
154   - public Map<String, String> getCurrSchDate() {
155   - return currSchDateMap;
156   - }
157   -
158   - /**
159   - * @Title: calcSchDateB
160   - * @Description: TODO(计算线路当前应该使用的排班日期)
161   - */
162   - public String calcSchDate(String lineCode) {
163   - Long t = System.currentTimeMillis();
164   - LineConfig conf = lineConfigData.get(lineCode);
165   -
166   - // 小于当天起始运营时间,则取前一天的排班
167   - String ct = fmtHHmm.print(t);
168   - if(ct.compareTo(conf.getStartOpt()) < 0)
169   - t -= 1000 * 60 * 60 * 24;
170   -
171   - String schDate = fmtyyyyMMdd.print(t);
172   - return schDate;
173   - }
174   -
175   - /**
176   - * @param @param lineCode 线路编码
177   - * @param @param schDate 班次日期 yyyy-MM-dd
178   - * @param @param forcePlan 强制从计划调度重新抓取
179   - * @Title: reloadSch
180   - * @Title: reloadSch
181   - * @Description: TODO(重新载入排班)
182   - */
183   - public int reloadSch(String lineCode, String schDate, boolean forcePlan) {
184   - try {
185   - List<ScheduleRealInfo> list;
186   -
187   - if (forcePlan)
188   - removeRealSch(lineCode, schDate);
189   - else
190   - clearRAMData(lineCode);
191   -
192   - if (existRealSch(lineCode, schDate))
193   - list = loadRealSch(lineCode, schDate);// 从实际排班表加载
194   - else {
195   - list = loadPlanSch(lineCode, schDate);// 从计划排班表加载
196   - // 写入数据库
197   - batchSave(list);
198   - }
199   -
200   - //更新线路和班次日期对照
201   - currSchDateMap.put(lineCode, schDate);
202   - //添加到缓存
203   - putAll(list);
204   -
205   - //标记首末班
206   - FirstAndLastHandler.marks(list);
207   -
208   - Set<String> lps = searchAllLP(list);
209   - for (String lp : lps) {
210   - //计算“起点站应到”时间
211   - schAttrCalculator.calcQdzTimePlan(lpScheduleMap.get(lineCode + "_" + lp));
212   - }
213   - Set<String> cars = searchAllCars(list);
214   - for (String nbbm : cars) {
215   - //车辆 ——> 要执行的班次对照
216   - reCalcExecPlan(nbbm);
217   - }
218   -
219   - //分组计划用车
220   - reCalcLineNbbms();
221   - // 页面 翻班通知
222   - //sendUtils.shiftSchedule(lineCode);
223   - } catch (Exception e) {
224   - logger.error("", e);
225   - return -1;
226   - }
227   -
228   - return 0;
229   - }
230   -
231   - public int reloadSch(String lineCode) {
232   - return reloadSch(lineCode, calcSchDate(lineCode), true);
233   - }
234   -
235   - /**
236   - * @Title: searchAllCars
237   - * @Description: TODO(搜索班次集合中的车辆)
238   - */
239   - private Set<String> searchAllCars(List<ScheduleRealInfo> list) {
240   - Set<String> cars = new HashSet<>();
241   - for (ScheduleRealInfo sch : list)
242   - cars.add(sch.getClZbh());
243   -
244   - return cars;
245   - }
246   -
247   - /**
248   - * @Title: searchAllCars
249   - * @Description: TODO(搜索班次集合中的路牌)
250   - */
251   - private Set<String> searchAllLP(List<ScheduleRealInfo> list) {
252   - Set<String> lps = new HashSet<>();
253   - for (ScheduleRealInfo sch : list)
254   - lps.add(sch.getLpName());
255   -
256   - return lps;
257   - }
258   -
259   - private void putAll(List<ScheduleRealInfo> list) {
260   - for (ScheduleRealInfo sch : list)
261   - put(sch);
262   - }
263   -
264   - /**
265   - * @param @param lineCode 线路编码
266   - * @param @param schDate 班次日期 yyyy-MM-dd
267   - * @Title: removeRealSch
268   - * @Description: TODO(清除实际排班,包括数据库和内存数据)
269   - */
270   - public void removeRealSch(String lineCode, String schDate) throws Exception {
271   - try {
272   - // 清理数据库数据
273   - schRepository.deleteByLineCodeAndDate(lineCode + "", schDate);
274   -
275   - // 清理内存数据
276   - clearRAMData(lineCode + "");
277   - } catch (Exception e) {
278   - logger.error("removeRealSch error, " + lineCode + " -" + schDate, e);
279   - throw e;
280   - }
281   - }
282   -
283   - /**
284   - * @Title: clearRAMData
285   - * @Description: TODO(清理内存数据)
286   - */
287   - public void clearRAMData(String lineCode) {
288   - int count = 0;
289   - List<ScheduleRealInfo> remList = new ArrayList<>();
290   - Collection<ScheduleRealInfo> all = nbbmScheduleMap.values();
291   - for (ScheduleRealInfo sch : all) {
292   - if (sch.getXlBm().equals(lineCode))
293   - remList.add(sch);
294   - }
295   -
296   - for (ScheduleRealInfo sch : remList) {
297   - if (null != sch) {
298   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
299   - id2SchedulMap.remove(sch.getId());
300   - count++;
301   -
302   - //清理路牌对照
303   - lpScheduleMap.removeAll(sch.getXlBm() + "_" + sch.getLpName());
304   -
305   - //清除车辆 ——> 执行班次对照
306   - carExecutePlanMap.remove(sch.getClZbh());
307   - }
308   - }
309   - //清理计划排班
310   - schedulePlanMap.remove(lineCode);
311   -
312   - remList.clear();
313   - remList = null;
314   - logger.info(lineCode + "排班清理 " + count);
315   - }
316   -
317   - /**
318   - * @Title: existRealSch
319   - * @Description: TODO(实际排班是否已存在)
320   - */
321   - public boolean existRealSch(String lineCode, String schDate) {
322   - int count = schRepository.countByLineCodeAndDate(lineCode, schDate);
323   - return count > 0;
324   - }
325   -
326   - /**
327   - * @Title: loadRealSch
328   - * @Description: TODO(从实际排班表加载数据)
329   - */
330   - public List<ScheduleRealInfo> loadRealSch(String lineCode, String schDate) {
331   - return schRepository.findByLineCodeAndDate(lineCode, schDate);
332   - }
333   -
334   - /**
335   - * @Title: loadPlanSch
336   - * @Description: TODO(从计划排班表加载数据)
337   - */
338   - public List<ScheduleRealInfo> loadPlanSch(String lineCode, String schDate) {
339   - //logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate);
340   - List<ScheduleRealInfo> realList = new ArrayList<>();
341   -
342   - try {
343   - Map<String, Object> data = new HashMap<>();
344   -
345   - data.put("scheduleDate_eq", fmtyyyyMMdd.parseDateTime(schDate).toDate());
346   - data.put("xlBm_eq", lineCode);
347   -
348   - // 查询计划排班
349   - List<SchedulePlanInfo> planItr = cleanSchPlanItr(schPlanService.list(data).iterator());
350   - //保存一份原始计划排班数据
351   - schedulePlanMap.put(lineCode, planItr);
352   -
353   - // 转换为实际排班
354   - realList = JSONArray.parseArray(JSON.toJSONString(planItr), ScheduleRealInfo.class);
355   - logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate + ", size:" + realList.size());
356   -
357   - Date d = new Date();
358   - SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
359   - String fcsj;
360   - for (ScheduleRealInfo sch : realList) {
361   - sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime()));
362   - sch.setRealExecDate(sch.getScheduleDateStr());
363   - sch.setCreateDate(d);
364   -
365   - if (StringUtils.isEmpty(sch.getFcsj()))
366   - sch.setFcsj("00:00");
367   -
368   - if (sch.getFcsj().equals("24:00"))
369   - sch.setFcsj("23:59");
370   -
371   - if (sch.getFcsj().substring(0, 2).equals("24")) {
372   - sch.setFcsj("00" + sch.getFcsj().substring(2));
373   - }
374   -
375   - fcsj = sch.getFcsj().trim();
376   - //处理一下发车时间格式没有:号的问题
377   - if (fcsj.indexOf(":") == -1 && fcsj.length() >= 4) {
378   - sch.setFcsj(fcsj.substring(0, 2) + ":" + fcsj.substring(2, 4));
379   - }
380   -
381   - try {
382   - sdf.parse(sch.getFcsj());
383   - } catch (ParseException e) {
384   - //发车时间仍然校验不过的,直接写成00:00
385   - sch.setFcsj("00:00");
386   - }
387   - sch.setDfsj(sch.getFcsj());
388   -
389   - // 计划终点时间
390   - if (sch.getBcsj() != null) {
391   - sch.setZdsj(fmtHHmm.print(fmtHHmm.parseMillis(sch.getFcsj()) + (sch.getBcsj() * 60 * 1000)));
392   - sch.setLate(false);
393   - }
394   -
395   - //售票员为空设置为""字符串
396   - if (StringUtils.isEmpty(sch.getsGh())) {
397   - sch.setsGh("");
398   - sch.setsName("");
399   - }
400   - sch.setJhlcOrig(sch.getJhlc());
401   - //保留备注
402   - if (StringUtils.isNotEmpty(sch.getRemark()))
403   - sch.setRemarks(sch.getRemark());
404   - }
405   - } catch (Exception e) {
406   - logger.error("", e);
407   - }
408   -
409   - return realList;
410   - }
411   -
412   -
413   - public synchronized long getId(){
414   - if(sch_max_id==-1){
415   - sch_max_id = schRepository.getMaxId();
416   - if(null == sch_max_id)
417   - sch_max_id = 3000L;//留一点空间补数据用
418   - sch_max_id += 5;
419   - }
420   - else
421   - sch_max_id ++;
422   - return sch_max_id;
423   - }
424   -
425   - /**
426   - * @Title: batchSave
427   - * @Description: TODO(批量入库)
428   - */
429   - private void batchSave(List<ScheduleRealInfo> list) {
430   - SimpleDateFormat sdfyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
431   - for (ScheduleRealInfo item : list) {
432   - item.setSpId(item.getId());// 保留原始的计划ID
433   - item.setId(getId());// 设置ID
434   - item.setScheduleDateStr(sdfyyyyMMdd.format(item.getScheduleDate()));
435   - }
436   -
437   - //编程式事务
438   - DataSourceTransactionManager tran = new DataSourceTransactionManager(jdbcTemplate.getDataSource());
439   - DefaultTransactionDefinition def = new DefaultTransactionDefinition();
440   - def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
441   - TransactionStatus status = tran.getTransaction(def);
442   -
443   - try{
444   - final List<ScheduleRealInfo> pstList = list;
445   - //写入
446   - jdbcTemplate.batchUpdate("insert into bsth_c_s_sp_info_real(id,bc_type,bcs,bcsj,cl_zbh,create_date,dfsj,directive_state,fcno,fcsj,fcsj_actual,j_gh,j_name,jhlc,lp_name,qdz_code,qdz_name,real_exec_date,remarks,s_gh,s_name,schedule_date,schedule_date_str,sflj,sp_id,status,update_date,xl_bm,xl_dir,xl_name,zdsj,zdsj_actual,zdz_code,zdz_name,ccno,df_auto,fgs_bm,fgs_name,gs_bm,gs_name,online,adjust_exps,reissue,jhlc_orig,sigin_compate,drift_status,cc_service,major_station_name)" +
447   - " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", new BatchPreparedStatementSetter() {
448   - @Override
449   - public void setValues(PreparedStatement ps, int i) throws SQLException {
450   - ScheduleRealInfo sch = pstList.get(i);
451   - ps.setLong(1, sch.getId());
452   - ps.setString(2, sch.getBcType());
453   - ps.setInt(3, sch.getBcs()==null?0:sch.getBcs());
454   - ps.setInt(4, sch.getBcsj()==null?0:sch.getBcsj());
455   - ps.setString(5, sch.getClZbh());
456   - ps.setTimestamp(6, new java.sql.Timestamp(sch.getCreateDate().getTime()));
457   - ps.setString(7, sch.getDfsj());
458   - ps.setInt(8, sch.getDirectiveState());
459   - ps.setInt(9, sch.getFcno()==null?0:sch.getFcno());
460   - ps.setString(10, sch.getFcsj());
461   - ps.setString(11, sch.getFcsjActual());
462   - ps.setString(12, sch.getjGh());
463   - ps.setString(13, sch.getjName());
464   - ps.setDouble(14, sch.getJhlc());
465   - ps.setString(15, sch.getLpName());
466   - ps.setString(16, sch.getQdzCode());
467   - ps.setString(17, sch.getQdzName());
468   - ps.setString(18, sch.getRealExecDate());
469   - ps.setString(19, sch.getRemarks());
470   - ps.setString(20, sch.getsGh());
471   - ps.setString(21, sch.getsName());
472   - ps.setTimestamp(22, new java.sql.Timestamp(sch.getScheduleDate().getTime()));
473   - ps.setString(23, sch.getScheduleDateStr());
474   - ps.setBoolean(24, sch.isSflj());
475   - ps.setLong(25, sch.getSpId());
476   - ps.setInt(26, sch.getStatus());
477   - ps.setTimestamp(27, new java.sql.Timestamp(sch.getUpdateDate().getTime()));
478   - ps.setString(28, sch.getXlBm());
479   - ps.setString(29, sch.getXlDir());
480   - ps.setString(30, sch.getXlName());
481   - ps.setString(31, sch.getZdsj());
482   - ps.setString(32, sch.getZdsjActual());
483   - ps.setString(33, sch.getZdzCode());
484   - ps.setString(34, sch.getZdzName());
485   - ps.setInt(35, sch.getCcno()==null?0:sch.getCcno());
486   - ps.setBoolean(36, sch.isDfAuto());
487   - ps.setString(37, sch.getFgsBm());
488   - ps.setString(38, sch.getFgsName());
489   - ps.setString(39, sch.getGsBm());
490   - ps.setString(40, sch.getGsName());
491   - ps.setBoolean(41, sch.isOnline());
492   - ps.setString(42, sch.getAdjustExps());
493   - ps.setBoolean(43, sch.isReissue());
494   - ps.setDouble(44, sch.getJhlcOrig());
495   - ps.setInt(45, sch.getSiginCompate());
496   - ps.setInt(46, sch.getDriftStatus());
497   - ps.setBoolean(47, sch.isCcService());
498   - ps.setString(48, sch.getMajorStationName());
499   - }
500   -
501   - @Override
502   - public int getBatchSize() {
503   - return pstList.size();
504   - }
505   - });
506   -
507   - tran.commit(status);
508   - }catch (Exception e){
509   - tran.rollback(status);
510   - logger.error("real schedule batchSave error...", e);
511   - }
512   - // 入库
513   - //new BatchSaveUtils<ScheduleRealInfo>().saveList(list, ScheduleRealInfo.class);
514   - }
515   -
516   - public List<SchedulePlanInfo> cleanSchPlanItr(Iterator<SchedulePlanInfo> itrab) {
517   - List<SchedulePlanInfo> list = new ArrayList<>();
518   -
519   - SchedulePlanInfo sp;
520   - while (itrab.hasNext()) {
521   - sp = itrab.next();
522   - sp.setSchedulePlan(null);
523   - sp.setCreateBy(null);
524   - sp.setUpdateBy(null);
525   - list.add(sp);
526   - }
527   - return list;
528   - }
529   -
530   - /**
531   - * @Title: findByLineCode
532   - * @Description: TODO(lineCode 获取班次)
533   - */
534   - public List<ScheduleRealInfo> findByLineCode(String lineCode) {
535   - List<ScheduleRealInfo> rs = new ArrayList<>();
536   -
537   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
538   - for (ScheduleRealInfo sch : schs) {
539   - if (sch.getXlBm().equals(lineCode))
540   - rs.add(sch);
541   - }
542   - return rs;
543   - }
544   -
545   - /**
546   - * @Title: findByLineCode
547   - * @Description: TODO(lineList 获取班次)
548   - */
549   - public Map<String, Collection<ScheduleRealInfo>> findByLineCodes(List<String> lineList) {
550   - ArrayListMultimap<String, ScheduleRealInfo> mMap = ArrayListMultimap.create();
551   -
552   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
553   - for (ScheduleRealInfo sch : schs) {
554   - if (lineList.contains(sch.getXlBm())) {
555   - mMap.put(sch.getXlBm(), sch);
556   - }
557   - }
558   - return mMap.asMap();
559   - }
560   -
561   - /**
562   - * @Title: findCarByLineCode
563   - * @Description: TODO(线路下运营的车辆)
564   - */
565   - public Set<String> findCarByLineCode(String lineCode) {
566   - /*Set<String> rs = new HashSet<>();
567   -
568   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
569   - for (ScheduleRealInfo sch : schs) {
570   - if (sch.getXlBm().equals(lineCode))
571   - rs.add(sch.getClZbh());
572   - }
573   -*/
574   - return lineNbbmsMap.get(lineCode);
575   - }
576   -
577   - public List<ScheduleRealInfo> findByNbbm(String nbbm) {
578   - return nbbmScheduleMap.get(nbbm);
579   - }
580   -
581   - /**
582   - * @Title: findByLineAndUpDown
583   - * @Description: TODO(lineCode 和走向获取班次)
584   - */
585   - public List<ScheduleRealInfo> findByLineAndUpDown(String lineCode, Integer upDown) {
586   - List<ScheduleRealInfo> list = findByLineCode(lineCode), rs = new ArrayList<>();
587   -
588   - for (ScheduleRealInfo sch : list) {
589   - if (sch.getXlDir().equals(upDown + ""))
590   - rs.add(sch);
591   - }
592   - return rs;
593   - }
594   -
595   - public ScheduleRealInfo get(long id) {
596   - return id2SchedulMap.get(id);
597   - }
598   -
599   -
600   - /**
601   - * @Title: next
602   - * @Description: TODO(下一个班次)
603   - */
604   - public ScheduleRealInfo next(ScheduleRealInfo sch) {
605   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
606   - //排序
607   - Collections.sort(list, schDFSJComparator);
608   - return next(list, sch);
609   - }
610   -
611   -
612   - /**
613   - * 下一个班次
614   - *
615   - * @param list 班次集合
616   - * @param sch 当前班次
617   - * @return
618   - */
619   - private ScheduleRealInfo next(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
620   - int outConfig = -1;
621   - LineConfig config = lineConfigData.get(sch.getXlBm());
622   - if (config != null)
623   - outConfig = config.getOutConfig();
624   -
625   - //限定出站既出场的停车场
626   - List<String> parks = config.findTwinsParkList();
627   - boolean limitPark = null != parks && parks.size() > 0;
628   - boolean flag = false;
629   - ScheduleRealInfo next = null;
630   - for (ScheduleRealInfo temp : list) {
631   - if (temp.getId() == sch.getId()) {
632   - flag = true;
633   - continue;
634   - }
635   - //忽略烂班
636   - if (temp.isDestroy())
637   - continue;
638   -
639   - //出站既出场,忽略出场班次
640   - if (outConfig == 2 && temp.getBcType().equals("out") && isEmptyMileage(temp)
641   - && (!limitPark || parks.contains(temp.getQdzCode())))
642   - continue;
643   -
644   - if (flag) {
645   - next = temp;
646   - break;
647   - }
648   - }
649   - return next;
650   - }
651   -
652   - private boolean isEmptyMileage(ScheduleRealInfo sch) {
653   - return sch.getBcsj() == 0 || sch.getJhlcOrig().intValue() == 0;
654   - }
655   -
656   - /**
657   - * 下一个班次
658   - *
659   - * @param list 班次集合
660   - * @param sch 当前班次
661   - * @return
662   - */
663   - private ScheduleRealInfo next2_lp(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
664   - int outConfig = -1;
665   - LineConfig config = lineConfigData.get(sch.getXlBm());
666   - if (config != null)
667   - outConfig = config.getOutConfig();
668   -
669   - boolean flag = false;
670   - ScheduleRealInfo next = null;
671   - for (ScheduleRealInfo temp : list) {
672   - if (temp.getId() == sch.getId()) {
673   - flag = true;
674   - continue;
675   - }
676   -
677   - if (flag) {
678   - next = temp;
679   - break;
680   - }
681   - }
682   - return next;
683   - }
684   -
685   - private ScheduleRealInfo next3_lp(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
686   - int outConfig = -1;
687   - LineConfig config = lineConfigData.get(sch.getXlBm());
688   - if (config != null)
689   - outConfig = config.getOutConfig();
690   -
691   - //限定出站既出场的停车场
692   - List<String> parks = config.findTwinsParkList();
693   - boolean limitPark = null != parks && parks.size() > 0;
694   - boolean flag = false;
695   - ScheduleRealInfo next = null;
696   - for (ScheduleRealInfo temp : list) {
697   - if (temp.getId() == sch.getId()) {
698   - flag = true;
699   - continue;
700   - }
701   -
702   - //出站既出场,忽略出场班次
703   - if (outConfig == 2 && temp.getBcType().equals("out") && isEmptyMileage(temp)
704   - && (!limitPark || parks.contains(temp.getQdzCode())))
705   - continue;
706   -
707   - if (flag) {
708   - next = temp;
709   - break;
710   - }
711   - }
712   - return next;
713   - }
714   -
715   - /**
716   - * 上一个班次
717   - *
718   - * @param sch
719   - * @return
720   - */
721   - public ScheduleRealInfo prev(ScheduleRealInfo sch) {
722   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
723   -
724   - //boolean flag = false;
725   - ScheduleRealInfo prev = null;
726   - int size = list.size();
727   -
728   - for (int i = 0; i < size; i++) {
729   - if (list.get(i).isDestroy())
730   - continue;
731   -
732   - if (list.get(i).getId().equals(sch.getId())) {
733   - return prev;
734   - }
735   - prev = list.get(i);
736   - }
737   - return prev;
738   - }
739   -
740   - /**
741   - * 是否是首班出场
742   - *
743   - * @param sch
744   - * @return
745   - */
746   - public boolean isFirstOut(ScheduleRealInfo sch) {
747   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
748   - try {
749   - if (list.get(0) == sch && sch.getBcType().equals("out"))
750   - return true;
751   - } catch (IndexOutOfBoundsException e) {
752   - logger.error("小小的数组越界,无伤大雅!");
753   - }
754   - return false;
755   - }
756   -
757   - public void put(ScheduleRealInfo sch) {
758   - schAttrCalculator
759   - .calcRealDate(sch)
760   - .calcAllTimeByFcsj(sch);
761   -
762   - nbbmScheduleMap.put(sch.getClZbh(), sch);
763   -
764   - //主键索引
765   - id2SchedulMap.put(sch.getId(), sch);
766   - //路牌对照表
767   - addLPMapp(sch);
768   -
769   - //跨24点的,再save一次
770   - if (!sch.getRealExecDate().equals(sch.getScheduleDateStr()))
771   - save(sch);
772   - }
773   -
774   - public void addLPMapp(ScheduleRealInfo sch) {
775   - lpScheduleMap.put(sch.getXlBm() + "_" + sch.getLpName(), sch);
776   - }
777   -
778   - public void delete(ScheduleRealInfo sch) {
779   - if (!sch.isSflj())
780   - return;
781   -
782   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
783   - id2SchedulMap.remove(sch.getId());
784   - lpScheduleMap.remove(sch.getXlBm() + "_" + sch.getLpName(), sch);
785   -
786   - //如果正在执行该班次
787   - if (carExecutePlanMap.get(sch.getClZbh()) == sch) {
788   - //重新计算车辆当前执行班次
789   - reCalcExecPlan(sch.getClZbh());
790   - }
791   - }
792   -
793   - public List<ScheduleRealInfo> updateQdzTimePlan(String lpName) {
794   - List<ScheduleRealInfo> list = lpScheduleMap.get(lpName);
795   - Collections.sort(list, schFCSJComparator);
796   - return schAttrCalculator.updateQdzTimePlan(list);
797   - }
798   -
799   - public List<ScheduleRealInfo> updateQdzTimePlan(ScheduleRealInfo sch) {
800   - return updateQdzTimePlan(sch.getXlBm() + "_" + sch.getLpName());
801   - }
802   -
803   - /**
804   - * @Title: doneSum
805   - * @Description: TODO(已完成班次总数)
806   - */
807   - public int doneSum(String clZbh) {
808   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(clZbh);
809   - int rs = 0;
810   -
811   - for (ScheduleRealInfo sch : list) {
812   - if (sch.getStatus() == 2 && !sch.isDestroy())
813   - rs++;
814   - }
815   - return rs;
816   - }
817   -
818   - public void save(ScheduleRealInfo sch) {
819   - sch.setUpdateDate(new Date());
820   - pstBuffer.add(sch);
821   - }
822   -
823   -
824   - /**
825   - * @Title: nextByBcType
826   - * @Description: TODO(获取下一个指定班次类型的班次)
827   - */
828   - public ScheduleRealInfo nextByBcType(String nbbm, String bcType) {
829   - List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
830   -
831   - Collections.sort(list, schFCSJComparator);
832   - ScheduleRealInfo sch = null;
833   - for (ScheduleRealInfo temp : list) {
834   - if (temp.getFcsjActual() == null) {
835   - sch = temp;
836   - break;
837   - }
838   - }
839   -
840   - return sch;
841   - }
842   -
843   -
844   - /**
845   - * 搜索离当前时间最近的一个指定类型的班次
846   - *
847   - * @param nbbm
848   - * @param bcType
849   - * @return
850   - */
851   - public ScheduleRealInfo searchNearByBcType(String nbbm, String bcType) {
852   - List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
853   - Collections.sort(list, schFCSJComparator);
854   -
855   - long t = System.currentTimeMillis();
856   - int distance = -1, diff;
857   -
858   - ScheduleRealInfo sch = null;
859   - for (ScheduleRealInfo temp : list) {
860   - diff = (int) Math.abs(temp.getDfsjT() - t);
861   - if (diff < distance || distance == -1) {
862   - sch = temp;
863   - distance = diff;
864   - }
865   - }
866   - return sch;
867   - }
868   -
869   - public List<ScheduleRealInfo> findByBcType(String nbbm, String bcType) {
870   - List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm), outList = new ArrayList<>();
871   -
872   - for (ScheduleRealInfo sch : all) {
873   - if (sch.getBcType().equals(bcType))
874   - outList.add(sch);
875   - }
876   - return outList;
877   - }
878   -
879   - public Collection<ScheduleRealInfo> findAll() {
880   - return nbbmScheduleMap.values();
881   - }
882   -
883   - public Collection<ScheduleRealInfo> findAllByLpContainer() {
884   - return lpScheduleMap.values();
885   - }
886   -
887   - public Collection<ScheduleRealInfo> findAllByIdContainer() {
888   - return id2SchedulMap.values();
889   - }
890   -
891   - public int getPstSize() {
892   - return pstBuffer.size();
893   - }
894   -
895   - public boolean addExecPlan(ScheduleRealInfo sch) {
896   - ScheduleRealInfo oldExec = executeCurr(sch.getClZbh());
897   - if (sch != null){
898   - if(sch.getStatus()==2)
899   - reCalcExecPlan(sch.getClZbh());
900   - else
901   - carExecutePlanMap.put(sch.getClZbh(), sch);
902   - }
903   - else
904   - carExecutePlanMap.remove(sch.getClZbh());
905   -
906   - return executeCurr(sch.getClZbh()) != oldExec;
907   - }
908   -
909   - public void removeExecPlan(String clzbh) {
910   - carExecutePlanMap.remove(clzbh);
911   - }
912   -
913   - public Map<String, ScheduleRealInfo> execPlanMap() {
914   - return carExecutePlanMap;
915   - }
916   -
917   - /**
918   - * 车辆当前执行的班次
919   - *
920   - * @param nbbm
921   - * @return
922   - */
923   - public ScheduleRealInfo executeCurr(String nbbm) {
924   - if(StringUtils.isEmpty(nbbm))
925   - return null;
926   - return carExecutePlanMap.get(nbbm);
927   - }
928   -
929   - /**
930   - * @param @param sch
931   - * @param @param newClZbh 新的车辆自编号
932   - * @Title: changeCar
933   - * @Description: TODO(班次换车) 返回有更新的班次
934   - */
935   - public List<ScheduleRealInfo> changeCar(ScheduleRealInfo sch, String newClZbh) {
936   - List<ScheduleRealInfo> ups = new ArrayList<>();
937   -
938   - String oldClZbh = sch.getClZbh();
939   - //变更相关映射信息
940   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
941   -
942   - sch.setClZbh(newClZbh);
943   - if (!nbbmScheduleMap.containsEntry(newClZbh, sch)) {
944   - nbbmScheduleMap.put(newClZbh, sch);
945   - }
946   -
947   - //重新计算车辆当前执行班次
948   - reCalcExecPlan(newClZbh);
949   - reCalcExecPlan(oldClZbh);
950   - //重新分组计划用车
951   - reCalcLineNbbms();
952   - return ups;
953   - }
954   -
955   - public void removeNbbm2SchMapp(ScheduleRealInfo sch) {
956   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
957   - }
958   -
959   - public void addNbbm2SchMapp(ScheduleRealInfo sch) {
960   - nbbmScheduleMap.put(sch.getClZbh(), sch);
961   - }
962   -
963   - public void reCalcExecPlan(String nbbm) {
964   - List<ScheduleRealInfo> list = nbbmScheduleMap.get(nbbm);
965   - Collections.sort(list, schDFSJComparator);
966   -
967   - ScheduleRealInfo sch = schAttrCalculator.calcCurrentExecSch(list);
968   - if(null != sch)
969   - carExecutePlanMap.put(nbbm, sch);
970   - else
971   - carExecutePlanMap.remove(nbbm);
972   - }
973   -
974   - /**
975   - * 空驶任务?
976   - * 出场、进场、直放、两点间空驶
977   - * @param sch
978   - * @return
979   - */
980   - public static boolean emptyService(ScheduleRealInfo sch){
981   - String type = sch.getBcType();
982   - return type.equals("out") || type.equals("in") || type.equals("venting") || type.equals("ldks");
983   - }
984   -
985   - @Autowired
986   - JdbcTemplate jdbcTemplate;
987   -
988   - /**
989   - * 删除实际排班
990   - *
991   - * @param lineCode
992   - * @return
993   - */
994   - public Map<String, Object> deleteRealSchedule(String lineCode) {
995   - Map<String, Object> rs = new HashMap<>();
996   -
997   - try {
998   - String rq = currSchDateMap.get(lineCode);
999   - if (StringUtils.isNotEmpty(rq)) {
1000   - List<ScheduleRealInfo> all = findByLineCode(lineCode);
1001   -
1002   - if(null != all && all.size() > 0){
1003   - //解除gps 和班次之间的关联
1004   - List<ScheduleRealInfo> unions = calcUnion(all, carExecutePlanMap.values());
1005   - for (ScheduleRealInfo sch : unions) {
1006   - removeExecPlan(sch.getClZbh());
1007   - }
1008   - //解除调度指令和班次的外键约束
1009   - StringBuilder inStr = new StringBuilder("(");
1010   - for (ScheduleRealInfo sch : all) {
1011   - inStr.append(sch.getId() + ",");
1012   - }
1013   - inStr.deleteCharAt(inStr.length() - 1).append(")");
1014   - jdbcTemplate.update(Constants.MULTI_REMOVE_DIRECTIVE_SCH_FK + " " + inStr.toString());
1015   - }
1016   -
1017   - //删除班次数据
1018   - removeRealSch(lineCode, rq);
1019   -
1020   - }
1021   - rs.put("status", ResponseCode.SUCCESS);
1022   - } catch (Exception e) {
1023   - logger.error("", e);
1024   - rs.put("status", ResponseCode.ERROR);
1025   - if (e instanceof DataIntegrityViolationException)
1026   - rs.put("msg", "失败,违反数据约束!!");
1027   - else
1028   - rs.put("msg", e.getMessage());
1029   - }
1030   -
1031   - return rs;
1032   - }
1033   -
1034   - /**
1035   - * 计算并集
1036   - *
1037   - * @param all
1038   - * @param sub
1039   - * @return
1040   - */
1041   - public List<ScheduleRealInfo> calcUnion(Collection<ScheduleRealInfo> c1, Collection<ScheduleRealInfo> c2) {
1042   - List<ScheduleRealInfo> rs = new ArrayList<>();
1043   -
1044   - for (ScheduleRealInfo sch : c1) {
1045   - if (c2.contains(sch)) {
1046   - rs.add(sch);
1047   - }
1048   - }
1049   - return rs;
1050   - }
1051   -
1052   - /**
1053   - * 覆盖一辆车的所有班次
1054   - *
1055   - * @param nbbm
1056   - * @param sets
1057   - */
1058   - public void replaceByNbbm(String nbbm, Collection<ScheduleRealInfo> sets) {
1059   - nbbmScheduleMap.removeAll(nbbm);
1060   - nbbmScheduleMap.putAll(nbbm, sets);
1061   - }
1062   -
1063   - /**
1064   - * 获取该班次所在路牌的下一个班次
1065   - *
1066   - * @param sch
1067   - * @return
1068   - */
1069   - public ScheduleRealInfo nextByLp(ScheduleRealInfo sch) {
1070   - List<ScheduleRealInfo> list = lpScheduleMap.get(sch.getXlBm() + "_" + sch.getLpName());
1071   - Collections.sort(list, schFCSJComparator);
1072   - return next3_lp(list, sch);
1073   - }
1074   -
1075   - /**
1076   - * 获取该班次所在路牌的下一个班次,不考虑场既是站
1077   - *
1078   - * @param sch
1079   - * @return
1080   - */
1081   - public ScheduleRealInfo nextByLp2(ScheduleRealInfo sch) {
1082   - List<ScheduleRealInfo> list = lpScheduleMap.get(sch.getXlBm() + "_" + sch.getLpName());
1083   - Collections.sort(list, schFCSJComparator);
1084   - return next2_lp(list, sch);
1085   - }
1086   -
1087   - public ArrayListMultimap<String, ScheduleRealInfo> getLpScheduleMap() {
1088   - return lpScheduleMap;
1089   - }
1090   -
1091   - /**
1092   - * 重新全量计算路牌下的班次关联性
1093   - * 临时性的函数
1094   - */
1095   - public void _test_reCalcLpSch() {
1096   - Map<String ,Collection<ScheduleRealInfo>> map = lpScheduleMap.asMap();
1097   - Set<String> ks = map.keySet();
1098   - for(String k : ks){
1099   - schAttrCalculator.calcQdzTimePlan(new ArrayList<ScheduleRealInfo>(map.get(k)));
1100   - }
1101   - }
1102   -
1103   - public int dbCount(String lineCode, String currSchDate) {
1104   - int count = -1;
1105   -
1106   - try{
1107   - count = jdbcTemplate.queryForObject("select count(*) from bsth_c_s_sp_info_real where schedule_date='"+currSchDate+"' and xl_bm='"+lineCode+"'", java.lang.Integer.class);
1108   -
1109   - }catch (Exception e){
1110   - logger.error("", e);
1111   - }
1112   - return count;
1113   - }
1114   -
1115   - /**
1116   - * 重新计算ID对照map
1117   - */
1118   - public int reCalcIdMaps(){
1119   - Collection<ScheduleRealInfo> all = findAll();
1120   - ConcurrentMap<Long, ScheduleRealInfo> id2SchedulMapCopy = new ConcurrentHashMap<>();
1121   -
1122   - for(ScheduleRealInfo sch : all){
1123   - id2SchedulMapCopy.put(sch.getId(), sch);
1124   - }
1125   -
1126   - id2SchedulMap = id2SchedulMapCopy;
1127   -
1128   - return id2SchedulMap.size();
1129   - }
1130   -
1131   - /**
1132   - * 重新计算线路计划用车
1133   - */
1134   - public void reCalcLineNbbms(){
1135   - HashMultimap<String, String> multimap = HashMultimap.create();
1136   -
1137   - Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
1138   - for (ScheduleRealInfo sch : schs) {
1139   - multimap.put(sch.getXlBm(), sch.getClZbh());
1140   - }
1141   -
1142   - lineNbbmsMap = multimap;
1143   - }
1144   -
1145   - public String sizeString(){
1146   - return id2SchedulMap.size() + "/" + nbbmScheduleMap.size();
1147   - }
1148   -
1149   -
1150   - /**
1151   - * 按公司编码分组数据
1152   - */
1153   - public void groupByGsbm(){
1154   - Collection<ScheduleRealInfo> all = findAll();
1155   - ListMultimap<String, ScheduleRealInfo> gsBmMaps = ArrayListMultimap.create();
1156   -
1157   - for(ScheduleRealInfo sch : all){
1158   - gsBmMaps.put(sch.getGsBm(), sch);
1159   - }
1160   -
1161   - if(gsBmMaps.size() > 0){
1162   - gsBmScheduleMap = null;
1163   - gsBmScheduleMap = gsBmMaps;
1164   - }
1165   - }
1166   -
1167   - public Collection<ScheduleRealInfo> findByGsbm(String gsbm){
1168   - return gsBmScheduleMap.get(gsbm);
1169   - }
1170   - /**
1171   - * 删除班次,删除内存中未清理掉的非当天的班次
1172   - * @createDate 2019.05.13
1173   - * @author zhangxianzhou
1174   - * @param sch
1175   - */
1176   - public void deleteBC(ScheduleRealInfo sch) {
1177   - nbbmScheduleMap.remove(sch.getClZbh(), sch);
1178   - id2SchedulMap.remove(sch.getId());
1179   - lpScheduleMap.remove(sch.getXlBm() + "_" + sch.getLpName(), sch);
1180   - //如果正在执行该班次
1181   - if (carExecutePlanMap.get(sch.getClZbh()) == sch) {
1182   - //重新计算车辆当前执行班次
1183   - reCalcExecPlan(sch.getClZbh());
1184   - }
1185   - }
1186   -
1187   - /**
1188   - ** 用于重置维修上报计数,一般只应该在翻班的时候调用
1189   - */
1190   - public void resetRepairReport(String incode) {
1191   - incode2report.remove(incode);
1192   - }
1193   -
1194   - public RepairReport getLastestRepairReport(String incode) {
1195   - return incode2report.get(incode);
1196   - }
1197   -
1198   - public void setLastestRepairReport(RepairReport rr) {
1199   - incode2report.put(rr.getIncode(), rr);
1200   - }
  1 +package com.bsth.data.schedule;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.bsth.common.Constants;
  6 +import com.bsth.common.ResponseCode;
  7 +import com.bsth.data.LineConfigData;
  8 +import com.bsth.data.gpsdata_v2.GpsRealData;
  9 +import com.bsth.data.gpsdata_v2.rfid.handle.RfidDataHandler;
  10 +import com.bsth.data.gpsdata_v2.utils.GpsDataRecovery;
  11 +import com.bsth.data.schedule.f_a_l.FirstAndLastHandler;
  12 +import com.bsth.entity.realcontrol.LineConfig;
  13 +import com.bsth.entity.realcontrol.ScheduleRealInfo;
  14 +import com.bsth.entity.report.RepairReport;
  15 +import com.bsth.entity.schedule.SchedulePlanInfo;
  16 +import com.bsth.repository.realcontrol.ScheduleRealInfoRepository;
  17 +import com.bsth.service.schedule.SchedulePlanInfoService;
  18 +import com.bsth.websocket.handler.SendUtils;
  19 +import com.google.common.collect.ArrayListMultimap;
  20 +import com.google.common.collect.HashMultimap;
  21 +import com.google.common.collect.ListMultimap;
  22 +import com.google.common.collect.Multimaps;
  23 +import org.apache.commons.lang3.StringUtils;
  24 +import org.joda.time.format.DateTimeFormat;
  25 +import org.joda.time.format.DateTimeFormatter;
  26 +import org.slf4j.Logger;
  27 +import org.slf4j.LoggerFactory;
  28 +import org.springframework.beans.factory.annotation.Autowired;
  29 +import org.springframework.dao.DataIntegrityViolationException;
  30 +import org.springframework.jdbc.core.BatchPreparedStatementSetter;
  31 +import org.springframework.jdbc.core.JdbcTemplate;
  32 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  33 +import org.springframework.stereotype.Component;
  34 +import org.springframework.transaction.TransactionDefinition;
  35 +import org.springframework.transaction.TransactionStatus;
  36 +import org.springframework.transaction.support.DefaultTransactionDefinition;
  37 +
  38 +import java.sql.PreparedStatement;
  39 +import java.sql.SQLException;
  40 +import java.text.ParseException;
  41 +import java.text.SimpleDateFormat;
  42 +import java.util.*;
  43 +import java.util.concurrent.ConcurrentHashMap;
  44 +import java.util.concurrent.ConcurrentLinkedQueue;
  45 +import java.util.concurrent.ConcurrentMap;
  46 +
  47 +/**
  48 + * @author PanZhao
  49 + * @ClassName: DayOfSchedule
  50 + * @Description: TODO(当日实际排班)
  51 + * @date 2016年8月15日 上午10:16:12
  52 + */
  53 +@Component
  54 +public class DayOfSchedule {
  55 +
  56 + Logger logger = LoggerFactory.getLogger(this.getClass());
  57 +
  58 + //按线路分组的 “原始计划” 排班数据
  59 + public static Map<String, List<SchedulePlanInfo>> schedulePlanMap;
  60 +
  61 + // 按车辆索引的班次数据
  62 + private static ListMultimap<String, ScheduleRealInfo> nbbmScheduleMap;
  63 +
  64 + // 按营运公司索引的班次数据
  65 + private static ListMultimap<String, ScheduleRealInfo> gsBmScheduleMap;
  66 +
  67 + //按线路索引计划用车
  68 + private static HashMultimap<String, String> lineNbbmsMap;
  69 +
  70 + //按路牌索引班次数据 线路编码_路牌名称 ——> 班次list
  71 + private static ArrayListMultimap<String, ScheduleRealInfo> lpScheduleMap;
  72 +
  73 + // 班次主键映射
  74 + private static ConcurrentMap<Long, ScheduleRealInfo> id2SchedulMap;
  75 +
  76 + //车辆 ——> 当前执行班次
  77 + private static ConcurrentMap<String, ScheduleRealInfo> carExecutePlanMap;
  78 +
  79 + // 持久化
  80 + public static ConcurrentLinkedQueue<ScheduleRealInfo> pstBuffer;
  81 +
  82 + // 排序器
  83 + private static ScheduleComparator.FCSJ schFCSJComparator;
  84 +
  85 + private static ScheduleComparator.DFSJ schDFSJComparator;
  86 +
  87 + private static Long sch_max_id=-1L;
  88 +
  89 + private Map<String, RepairReport> incode2report = new ConcurrentHashMap<String, RepairReport>();
  90 +
  91 + @Autowired
  92 + LineConfigData lineConfigData;
  93 +
  94 + @Autowired
  95 + ScheduleRealInfoRepository schRepository;
  96 +
  97 + @Autowired
  98 + SchedulePlanInfoService schPlanService;
  99 +
  100 + @Autowired
  101 + SchAttrCalculator schAttrCalculator;
  102 +
  103 + @Autowired
  104 + SendUtils sendUtils;
  105 +
  106 + @Autowired
  107 + GpsRealData gpsRealData;
  108 +
  109 + /**
  110 + * 线路当前使用的排班的日期
  111 + */
  112 + public static Map<String, String> currSchDateMap;
  113 +
  114 + static {
  115 + nbbmScheduleMap = ArrayListMultimap.create();
  116 + nbbmScheduleMap = Multimaps.synchronizedListMultimap(nbbmScheduleMap);
  117 +
  118 + gsBmScheduleMap = ArrayListMultimap.create();
  119 + lpScheduleMap = ArrayListMultimap.create();
  120 + lineNbbmsMap = HashMultimap.create();
  121 +
  122 + id2SchedulMap = new ConcurrentHashMap<>();
  123 + pstBuffer = new ConcurrentLinkedQueue<>();
  124 + schFCSJComparator = new ScheduleComparator.FCSJ();
  125 + schDFSJComparator = new ScheduleComparator.DFSJ();
  126 + currSchDateMap = new HashMap<>();
  127 + carExecutePlanMap = new ConcurrentHashMap<>();
  128 +
  129 + schedulePlanMap = new HashMap<>();
  130 + }
  131 +
  132 + @Autowired
  133 + LineConfigData lineConfigs;
  134 +
  135 + @Autowired
  136 + GpsDataRecovery gpsDataRecovery;
  137 +
  138 + private static DateTimeFormatter fmtyyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd"), fmtHHmm = DateTimeFormat.forPattern("HH:mm");
  139 +
  140 + //数据恢复
  141 + public void dataRecovery() {
  142 + Collection<LineConfig> confs = lineConfigs.getAll();
  143 + String lineCode, currSchDate;
  144 + for (LineConfig conf : confs) {
  145 + lineCode = conf.getLine().getLineCode();
  146 + currSchDate = calcSchDate(lineCode);
  147 + //加载班次数据
  148 + reloadSch(lineCode, currSchDate, false);
  149 + }
  150 +
  151 + //恢复gps数据
  152 + gpsDataRecovery.recovery();
  153 + }
  154 +
  155 + public Map<String, String> getCurrSchDate() {
  156 + return currSchDateMap;
  157 + }
  158 +
  159 + /**
  160 + * @Title: calcSchDateB
  161 + * @Description: TODO(计算线路当前应该使用的排班日期)
  162 + */
  163 + public String calcSchDate(String lineCode) {
  164 + Long t = System.currentTimeMillis();
  165 + LineConfig conf = lineConfigData.get(lineCode);
  166 +
  167 + // 小于当天起始运营时间,则取前一天的排班
  168 + String ct = fmtHHmm.print(t);
  169 + if(ct.compareTo(conf.getStartOpt()) < 0)
  170 + t -= 1000 * 60 * 60 * 24;
  171 +
  172 + String schDate = fmtyyyyMMdd.print(t);
  173 + return schDate;
  174 + }
  175 +
  176 + /**
  177 + * @param @param lineCode 线路编码
  178 + * @param @param schDate 班次日期 yyyy-MM-dd
  179 + * @param @param forcePlan 强制从计划调度重新抓取
  180 + * @Title: reloadSch
  181 + * @Title: reloadSch
  182 + * @Description: TODO(重新载入排班)
  183 + */
  184 + public int reloadSch(String lineCode, String schDate, boolean forcePlan) {
  185 + try {
  186 + List<ScheduleRealInfo> list;
  187 +
  188 + if (forcePlan)
  189 + removeRealSch(lineCode, schDate);
  190 + else
  191 + clearRAMData(lineCode);
  192 +
  193 + if (existRealSch(lineCode, schDate))
  194 + list = loadRealSch(lineCode, schDate);// 从实际排班表加载
  195 + else {
  196 + list = loadPlanSch(lineCode, schDate);// 从计划排班表加载
  197 + // 写入数据库
  198 + batchSave(list);
  199 + }
  200 +
  201 + //更新线路和班次日期对照
  202 + currSchDateMap.put(lineCode, schDate);
  203 + //添加到缓存
  204 + putAll(list);
  205 +
  206 + //标记首末班
  207 + FirstAndLastHandler.marks(list);
  208 +
  209 + Set<String> lps = searchAllLP(list);
  210 + for (String lp : lps) {
  211 + //计算“起点站应到”时间
  212 + schAttrCalculator.calcQdzTimePlan(lpScheduleMap.get(lineCode + "_" + lp));
  213 + }
  214 + Set<String> cars = searchAllCars(list);
  215 + for (String nbbm : cars) {
  216 + //车辆 ——> 要执行的班次对照
  217 + reCalcExecPlan(nbbm);
  218 + }
  219 +
  220 + //分组计划用车
  221 + reCalcLineNbbms();
  222 + // 页面 翻班通知
  223 + //sendUtils.shiftSchedule(lineCode);
  224 + } catch (Exception e) {
  225 + logger.error("", e);
  226 + return -1;
  227 + }
  228 +
  229 + return 0;
  230 + }
  231 +
  232 + public int reloadSch(String lineCode) {
  233 + return reloadSch(lineCode, calcSchDate(lineCode), true);
  234 + }
  235 +
  236 + /**
  237 + * @Title: searchAllCars
  238 + * @Description: TODO(搜索班次集合中的车辆)
  239 + */
  240 + private Set<String> searchAllCars(List<ScheduleRealInfo> list) {
  241 + Set<String> cars = new HashSet<>();
  242 + for (ScheduleRealInfo sch : list)
  243 + cars.add(sch.getClZbh());
  244 +
  245 + return cars;
  246 + }
  247 +
  248 + /**
  249 + * @Title: searchAllCars
  250 + * @Description: TODO(搜索班次集合中的路牌)
  251 + */
  252 + private Set<String> searchAllLP(List<ScheduleRealInfo> list) {
  253 + Set<String> lps = new HashSet<>();
  254 + for (ScheduleRealInfo sch : list)
  255 + lps.add(sch.getLpName());
  256 +
  257 + return lps;
  258 + }
  259 +
  260 + private void putAll(List<ScheduleRealInfo> list) {
  261 + for (ScheduleRealInfo sch : list)
  262 + put(sch);
  263 + }
  264 +
  265 + /**
  266 + * @param @param lineCode 线路编码
  267 + * @param @param schDate 班次日期 yyyy-MM-dd
  268 + * @Title: removeRealSch
  269 + * @Description: TODO(清除实际排班,包括数据库和内存数据)
  270 + */
  271 + public void removeRealSch(String lineCode, String schDate) throws Exception {
  272 + try {
  273 + // 清理数据库数据
  274 + schRepository.deleteByLineCodeAndDate(lineCode + "", schDate);
  275 +
  276 + // 清理内存数据
  277 + clearRAMData(lineCode + "");
  278 + } catch (Exception e) {
  279 + logger.error("removeRealSch error, " + lineCode + " -" + schDate, e);
  280 + throw e;
  281 + }
  282 + }
  283 +
  284 + /**
  285 + * @Title: clearRAMData
  286 + * @Description: TODO(清理内存数据)
  287 + */
  288 + public void clearRAMData(String lineCode) {
  289 + int count = 0;
  290 + List<ScheduleRealInfo> remList = new ArrayList<>();
  291 + Collection<ScheduleRealInfo> all = nbbmScheduleMap.values();
  292 + for (ScheduleRealInfo sch : all) {
  293 + if (sch.getXlBm().equals(lineCode))
  294 + remList.add(sch);
  295 + }
  296 +
  297 + for (ScheduleRealInfo sch : remList) {
  298 + if (null != sch) {
  299 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  300 + id2SchedulMap.remove(sch.getId());
  301 + count++;
  302 +
  303 + //清理路牌对照
  304 + lpScheduleMap.removeAll(sch.getXlBm() + "_" + sch.getLpName());
  305 +
  306 + //清除车辆 ——> 执行班次对照
  307 + carExecutePlanMap.remove(sch.getClZbh());
  308 + }
  309 + }
  310 + //清理计划排班
  311 + schedulePlanMap.remove(lineCode);
  312 +
  313 + remList.clear();
  314 + remList = null;
  315 + logger.info(lineCode + "排班清理 " + count);
  316 + }
  317 +
  318 + /**
  319 + * @Title: existRealSch
  320 + * @Description: TODO(实际排班是否已存在)
  321 + */
  322 + public boolean existRealSch(String lineCode, String schDate) {
  323 + int count = schRepository.countByLineCodeAndDate(lineCode, schDate);
  324 + return count > 0;
  325 + }
  326 +
  327 + /**
  328 + * @Title: loadRealSch
  329 + * @Description: TODO(从实际排班表加载数据)
  330 + */
  331 + public List<ScheduleRealInfo> loadRealSch(String lineCode, String schDate) {
  332 + return schRepository.findByLineCodeAndDate(lineCode, schDate);
  333 + }
  334 +
  335 + /**
  336 + * @Title: loadPlanSch
  337 + * @Description: TODO(从计划排班表加载数据)
  338 + */
  339 + public List<ScheduleRealInfo> loadPlanSch(String lineCode, String schDate) {
  340 + //logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate);
  341 + List<ScheduleRealInfo> realList = new ArrayList<>();
  342 +
  343 + try {
  344 + Map<String, Object> data = new HashMap<>();
  345 +
  346 + data.put("scheduleDate_eq", fmtyyyyMMdd.parseDateTime(schDate).toDate());
  347 + data.put("xlBm_eq", lineCode);
  348 +
  349 + // 查询计划排班
  350 + List<SchedulePlanInfo> planItr = cleanSchPlanItr(schPlanService.list(data).iterator());
  351 + //保存一份原始计划排班数据
  352 + schedulePlanMap.put(lineCode, planItr);
  353 +
  354 + // 转换为实际排班
  355 + realList = JSONArray.parseArray(JSON.toJSONString(planItr), ScheduleRealInfo.class);
  356 + logger.info("从计划排班表恢复排班,lineCode: " + lineCode + ", schDate: " + schDate + ", size:" + realList.size());
  357 +
  358 + Date d = new Date();
  359 + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  360 + String fcsj;
  361 + for (ScheduleRealInfo sch : realList) {
  362 + sch.setScheduleDateStr(fmtyyyyMMdd.print(sch.getScheduleDate().getTime()));
  363 + sch.setRealExecDate(sch.getScheduleDateStr());
  364 + sch.setCreateDate(d);
  365 +
  366 + if (StringUtils.isEmpty(sch.getFcsj()))
  367 + sch.setFcsj("00:00");
  368 +
  369 + if (sch.getFcsj().equals("24:00"))
  370 + sch.setFcsj("23:59");
  371 +
  372 + if (sch.getFcsj().substring(0, 2).equals("24")) {
  373 + sch.setFcsj("00" + sch.getFcsj().substring(2));
  374 + }
  375 +
  376 + fcsj = sch.getFcsj().trim();
  377 + //处理一下发车时间格式没有:号的问题
  378 + if (fcsj.indexOf(":") == -1 && fcsj.length() >= 4) {
  379 + sch.setFcsj(fcsj.substring(0, 2) + ":" + fcsj.substring(2, 4));
  380 + }
  381 +
  382 + try {
  383 + sdf.parse(sch.getFcsj());
  384 + } catch (ParseException e) {
  385 + //发车时间仍然校验不过的,直接写成00:00
  386 + sch.setFcsj("00:00");
  387 + }
  388 + sch.setDfsj(sch.getFcsj());
  389 +
  390 + // 计划终点时间
  391 + if (sch.getBcsj() != null) {
  392 + sch.setZdsj(fmtHHmm.print(fmtHHmm.parseMillis(sch.getFcsj()) + (sch.getBcsj() * 60 * 1000)));
  393 + sch.setLate(false);
  394 + }
  395 +
  396 + //售票员为空设置为""字符串
  397 + if (StringUtils.isEmpty(sch.getsGh())) {
  398 + sch.setsGh("");
  399 + sch.setsName("");
  400 + }
  401 + sch.setJhlcOrig(sch.getJhlc());
  402 + //保留备注
  403 + if (StringUtils.isNotEmpty(sch.getRemark()))
  404 + sch.setRemarks(sch.getRemark());
  405 + }
  406 + } catch (Exception e) {
  407 + logger.error("", e);
  408 + }
  409 +
  410 + return realList;
  411 + }
  412 +
  413 +
  414 + public synchronized long getId(){
  415 + if(sch_max_id==-1){
  416 + sch_max_id = schRepository.getMaxId();
  417 + if(null == sch_max_id)
  418 + sch_max_id = 3000L;//留一点空间补数据用
  419 + sch_max_id += 5;
  420 + }
  421 + else
  422 + sch_max_id ++;
  423 + return sch_max_id;
  424 + }
  425 +
  426 + /**
  427 + * @Title: batchSave
  428 + * @Description: TODO(批量入库)
  429 + */
  430 + private void batchSave(List<ScheduleRealInfo> list) {
  431 + SimpleDateFormat sdfyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
  432 + for (ScheduleRealInfo item : list) {
  433 + item.setSpId(item.getId());// 保留原始的计划ID
  434 + item.setId(getId());// 设置ID
  435 + item.setScheduleDateStr(sdfyyyyMMdd.format(item.getScheduleDate()));
  436 + }
  437 +
  438 + //编程式事务
  439 + DataSourceTransactionManager tran = new DataSourceTransactionManager(jdbcTemplate.getDataSource());
  440 + DefaultTransactionDefinition def = new DefaultTransactionDefinition();
  441 + def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  442 + TransactionStatus status = tran.getTransaction(def);
  443 +
  444 + try{
  445 + final List<ScheduleRealInfo> pstList = list;
  446 + //写入
  447 + jdbcTemplate.batchUpdate("insert into bsth_c_s_sp_info_real(id,bc_type,bcs,bcsj,cl_zbh,create_date,dfsj,directive_state,fcno,fcsj,fcsj_actual,j_gh,j_name,jhlc,lp_name,qdz_code,qdz_name,real_exec_date,remarks,s_gh,s_name,schedule_date,schedule_date_str,sflj,sp_id,status,update_date,xl_bm,xl_dir,xl_name,zdsj,zdsj_actual,zdz_code,zdz_name,ccno,df_auto,fgs_bm,fgs_name,gs_bm,gs_name,online,adjust_exps,reissue,jhlc_orig,sigin_compate,drift_status,cc_service,major_station_name)" +
  448 + " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", new BatchPreparedStatementSetter() {
  449 + @Override
  450 + public void setValues(PreparedStatement ps, int i) throws SQLException {
  451 + ScheduleRealInfo sch = pstList.get(i);
  452 + ps.setLong(1, sch.getId());
  453 + ps.setString(2, sch.getBcType());
  454 + ps.setInt(3, sch.getBcs()==null?0:sch.getBcs());
  455 + ps.setInt(4, sch.getBcsj()==null?0:sch.getBcsj());
  456 + ps.setString(5, sch.getClZbh());
  457 + ps.setTimestamp(6, new java.sql.Timestamp(sch.getCreateDate().getTime()));
  458 + ps.setString(7, sch.getDfsj());
  459 + ps.setInt(8, sch.getDirectiveState());
  460 + ps.setInt(9, sch.getFcno()==null?0:sch.getFcno());
  461 + ps.setString(10, sch.getFcsj());
  462 + ps.setString(11, sch.getFcsjActual());
  463 + ps.setString(12, sch.getjGh());
  464 + ps.setString(13, sch.getjName());
  465 + ps.setDouble(14, sch.getJhlc());
  466 + ps.setString(15, sch.getLpName());
  467 + ps.setString(16, sch.getQdzCode());
  468 + ps.setString(17, sch.getQdzName());
  469 + ps.setString(18, sch.getRealExecDate());
  470 + ps.setString(19, sch.getRemarks());
  471 + ps.setString(20, sch.getsGh());
  472 + ps.setString(21, sch.getsName());
  473 + ps.setTimestamp(22, new java.sql.Timestamp(sch.getScheduleDate().getTime()));
  474 + ps.setString(23, sch.getScheduleDateStr());
  475 + ps.setBoolean(24, sch.isSflj());
  476 + ps.setLong(25, sch.getSpId());
  477 + ps.setInt(26, sch.getStatus());
  478 + ps.setTimestamp(27, new java.sql.Timestamp(sch.getUpdateDate().getTime()));
  479 + ps.setString(28, sch.getXlBm());
  480 + ps.setString(29, sch.getXlDir());
  481 + ps.setString(30, sch.getXlName());
  482 + ps.setString(31, sch.getZdsj());
  483 + ps.setString(32, sch.getZdsjActual());
  484 + ps.setString(33, sch.getZdzCode());
  485 + ps.setString(34, sch.getZdzName());
  486 + ps.setInt(35, sch.getCcno()==null?0:sch.getCcno());
  487 + ps.setBoolean(36, sch.isDfAuto());
  488 + ps.setString(37, sch.getFgsBm());
  489 + ps.setString(38, sch.getFgsName());
  490 + ps.setString(39, sch.getGsBm());
  491 + ps.setString(40, sch.getGsName());
  492 + ps.setBoolean(41, sch.isOnline());
  493 + ps.setString(42, sch.getAdjustExps());
  494 + ps.setBoolean(43, sch.isReissue());
  495 + ps.setDouble(44, sch.getJhlcOrig());
  496 + ps.setInt(45, sch.getSiginCompate());
  497 + ps.setInt(46, sch.getDriftStatus());
  498 + ps.setBoolean(47, sch.isCcService());
  499 + ps.setString(48, sch.getMajorStationName());
  500 + }
  501 +
  502 + @Override
  503 + public int getBatchSize() {
  504 + return pstList.size();
  505 + }
  506 + });
  507 +
  508 + tran.commit(status);
  509 + }catch (Exception e){
  510 + tran.rollback(status);
  511 + logger.error("real schedule batchSave error...", e);
  512 + }
  513 + // 入库
  514 + //new BatchSaveUtils<ScheduleRealInfo>().saveList(list, ScheduleRealInfo.class);
  515 + }
  516 +
  517 + public List<SchedulePlanInfo> cleanSchPlanItr(Iterator<SchedulePlanInfo> itrab) {
  518 + List<SchedulePlanInfo> list = new ArrayList<>();
  519 +
  520 + SchedulePlanInfo sp;
  521 + while (itrab.hasNext()) {
  522 + sp = itrab.next();
  523 + sp.setSchedulePlan(null);
  524 + sp.setCreateBy(null);
  525 + sp.setUpdateBy(null);
  526 + list.add(sp);
  527 + }
  528 + return list;
  529 + }
  530 +
  531 + /**
  532 + * @Title: findByLineCode
  533 + * @Description: TODO(lineCode 获取班次)
  534 + */
  535 + public List<ScheduleRealInfo> findByLineCode(String lineCode) {
  536 + List<ScheduleRealInfo> rs = new ArrayList<>();
  537 +
  538 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  539 + for (ScheduleRealInfo sch : schs) {
  540 + if (sch.getXlBm().equals(lineCode))
  541 + rs.add(sch);
  542 + }
  543 + return rs;
  544 + }
  545 +
  546 + /**
  547 + * @Title: findByLineCode
  548 + * @Description: TODO(lineList 获取班次)
  549 + */
  550 + public Map<String, Collection<ScheduleRealInfo>> findByLineCodes(List<String> lineList) {
  551 + ArrayListMultimap<String, ScheduleRealInfo> mMap = ArrayListMultimap.create();
  552 +
  553 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  554 + for (ScheduleRealInfo sch : schs) {
  555 + if (lineList.contains(sch.getXlBm())) {
  556 + mMap.put(sch.getXlBm(), sch);
  557 + }
  558 + }
  559 + return mMap.asMap();
  560 + }
  561 +
  562 + /**
  563 + * @Title: findCarByLineCode
  564 + * @Description: TODO(线路下运营的车辆)
  565 + */
  566 + public Set<String> findCarByLineCode(String lineCode) {
  567 + /*Set<String> rs = new HashSet<>();
  568 +
  569 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  570 + for (ScheduleRealInfo sch : schs) {
  571 + if (sch.getXlBm().equals(lineCode))
  572 + rs.add(sch.getClZbh());
  573 + }
  574 +*/
  575 + return lineNbbmsMap.get(lineCode);
  576 + }
  577 +
  578 + public List<ScheduleRealInfo> findByNbbm(String nbbm) {
  579 + return nbbmScheduleMap.get(nbbm);
  580 + }
  581 +
  582 + /**
  583 + * @Title: findByLineAndUpDown
  584 + * @Description: TODO(lineCode 和走向获取班次)
  585 + */
  586 + public List<ScheduleRealInfo> findByLineAndUpDown(String lineCode, Integer upDown) {
  587 + List<ScheduleRealInfo> list = findByLineCode(lineCode), rs = new ArrayList<>();
  588 +
  589 + for (ScheduleRealInfo sch : list) {
  590 + if (sch.getXlDir().equals(upDown + ""))
  591 + rs.add(sch);
  592 + }
  593 + return rs;
  594 + }
  595 +
  596 + public ScheduleRealInfo get(long id) {
  597 + return id2SchedulMap.get(id);
  598 + }
  599 +
  600 +
  601 + /**
  602 + * @Title: next
  603 + * @Description: TODO(下一个班次)
  604 + */
  605 + public ScheduleRealInfo next(ScheduleRealInfo sch) {
  606 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  607 + //排序
  608 + Collections.sort(list, schDFSJComparator);
  609 + return next(list, sch);
  610 + }
  611 +
  612 +
  613 + /**
  614 + * 下一个班次
  615 + *
  616 + * @param list 班次集合
  617 + * @param sch 当前班次
  618 + * @return
  619 + */
  620 + private ScheduleRealInfo next(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
  621 + int outConfig = -1;
  622 + LineConfig config = lineConfigData.get(sch.getXlBm());
  623 + if (config != null)
  624 + outConfig = config.getOutConfig();
  625 +
  626 + //限定出站既出场的停车场
  627 + List<String> parks = config.findTwinsParkList();
  628 + boolean limitPark = null != parks && parks.size() > 0;
  629 + boolean flag = false;
  630 + ScheduleRealInfo next = null;
  631 + for (ScheduleRealInfo temp : list) {
  632 + if (temp.getId() == sch.getId()) {
  633 + flag = true;
  634 + continue;
  635 + }
  636 + //忽略烂班
  637 + if (temp.isDestroy())
  638 + continue;
  639 +
  640 + //出站既出场,忽略出场班次
  641 + if (outConfig == 2 && temp.getBcType().equals("out") && isEmptyMileage(temp)
  642 + && (!limitPark || parks.contains(temp.getQdzCode())))
  643 + continue;
  644 +
  645 + if (flag) {
  646 + next = temp;
  647 + break;
  648 + }
  649 + }
  650 + return next;
  651 + }
  652 +
  653 + private boolean isEmptyMileage(ScheduleRealInfo sch) {
  654 + return sch.getBcsj() == 0 || sch.getJhlcOrig().intValue() == 0;
  655 + }
  656 +
  657 + /**
  658 + * 下一个班次
  659 + *
  660 + * @param list 班次集合
  661 + * @param sch 当前班次
  662 + * @return
  663 + */
  664 + private ScheduleRealInfo next2_lp(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
  665 + int outConfig = -1;
  666 + LineConfig config = lineConfigData.get(sch.getXlBm());
  667 + if (config != null)
  668 + outConfig = config.getOutConfig();
  669 +
  670 + boolean flag = false;
  671 + ScheduleRealInfo next = null;
  672 + for (ScheduleRealInfo temp : list) {
  673 + if (temp.getId() == sch.getId()) {
  674 + flag = true;
  675 + continue;
  676 + }
  677 +
  678 + if (flag) {
  679 + next = temp;
  680 + break;
  681 + }
  682 + }
  683 + return next;
  684 + }
  685 +
  686 + private ScheduleRealInfo next3_lp(Collection<ScheduleRealInfo> list, ScheduleRealInfo sch) {
  687 + int outConfig = -1;
  688 + LineConfig config = lineConfigData.get(sch.getXlBm());
  689 + if (config != null)
  690 + outConfig = config.getOutConfig();
  691 +
  692 + //限定出站既出场的停车场
  693 + List<String> parks = config.findTwinsParkList();
  694 + boolean limitPark = null != parks && parks.size() > 0;
  695 + boolean flag = false;
  696 + ScheduleRealInfo next = null;
  697 + for (ScheduleRealInfo temp : list) {
  698 + if (temp.getId() == sch.getId()) {
  699 + flag = true;
  700 + continue;
  701 + }
  702 +
  703 + //出站既出场,忽略出场班次
  704 + if (outConfig == 2 && temp.getBcType().equals("out") && isEmptyMileage(temp)
  705 + && (!limitPark || parks.contains(temp.getQdzCode())))
  706 + continue;
  707 +
  708 + if (flag) {
  709 + next = temp;
  710 + break;
  711 + }
  712 + }
  713 + return next;
  714 + }
  715 +
  716 + /**
  717 + * 上一个班次
  718 + *
  719 + * @param sch
  720 + * @return
  721 + */
  722 + public ScheduleRealInfo prev(ScheduleRealInfo sch) {
  723 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  724 +
  725 + //boolean flag = false;
  726 + ScheduleRealInfo prev = null;
  727 + int size = list.size();
  728 +
  729 + for (int i = 0; i < size; i++) {
  730 + if (list.get(i).isDestroy())
  731 + continue;
  732 +
  733 + if (list.get(i).getId().equals(sch.getId())) {
  734 + return prev;
  735 + }
  736 + prev = list.get(i);
  737 + }
  738 + return prev;
  739 + }
  740 +
  741 + /**
  742 + * 是否是首班出场
  743 + *
  744 + * @param sch
  745 + * @return
  746 + */
  747 + public boolean isFirstOut(ScheduleRealInfo sch) {
  748 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(sch.getClZbh());
  749 + try {
  750 + if (list.get(0) == sch && sch.getBcType().equals("out"))
  751 + return true;
  752 + } catch (IndexOutOfBoundsException e) {
  753 + logger.error("小小的数组越界,无伤大雅!");
  754 + }
  755 + return false;
  756 + }
  757 +
  758 + public void put(ScheduleRealInfo sch) {
  759 + schAttrCalculator
  760 + .calcRealDate(sch)
  761 + .calcAllTimeByFcsj(sch);
  762 +
  763 + nbbmScheduleMap.put(sch.getClZbh(), sch);
  764 +
  765 + //主键索引
  766 + id2SchedulMap.put(sch.getId(), sch);
  767 + //路牌对照表
  768 + addLPMapp(sch);
  769 +
  770 + //跨24点的,再save一次
  771 + if (!sch.getRealExecDate().equals(sch.getScheduleDateStr()))
  772 + save(sch);
  773 + }
  774 +
  775 + public void addLPMapp(ScheduleRealInfo sch) {
  776 + lpScheduleMap.put(sch.getXlBm() + "_" + sch.getLpName(), sch);
  777 + }
  778 +
  779 + public void delete(ScheduleRealInfo sch) {
  780 + if (!sch.isSflj())
  781 + return;
  782 +
  783 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  784 + id2SchedulMap.remove(sch.getId());
  785 + lpScheduleMap.remove(sch.getXlBm() + "_" + sch.getLpName(), sch);
  786 +
  787 + //如果正在执行该班次
  788 + if (carExecutePlanMap.get(sch.getClZbh()) == sch) {
  789 + //重新计算车辆当前执行班次
  790 + reCalcExecPlan(sch.getClZbh());
  791 + }
  792 + }
  793 +
  794 + public List<ScheduleRealInfo> updateQdzTimePlan(String lpName) {
  795 + List<ScheduleRealInfo> list = lpScheduleMap.get(lpName);
  796 + Collections.sort(list, schFCSJComparator);
  797 + return schAttrCalculator.updateQdzTimePlan(list);
  798 + }
  799 +
  800 + public List<ScheduleRealInfo> updateQdzTimePlan(ScheduleRealInfo sch) {
  801 + return updateQdzTimePlan(sch.getXlBm() + "_" + sch.getLpName());
  802 + }
  803 +
  804 + /**
  805 + * @Title: doneSum
  806 + * @Description: TODO(已完成班次总数)
  807 + */
  808 + public int doneSum(String clZbh) {
  809 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(clZbh);
  810 + int rs = 0;
  811 +
  812 + for (ScheduleRealInfo sch : list) {
  813 + if (sch.getStatus() == 2 && !sch.isDestroy())
  814 + rs++;
  815 + }
  816 + return rs;
  817 + }
  818 +
  819 + public void save(ScheduleRealInfo sch) {
  820 + sch.setUpdateDate(new Date());
  821 + pstBuffer.add(sch);
  822 + }
  823 +
  824 +
  825 + /**
  826 + * @Title: nextByBcType
  827 + * @Description: TODO(获取下一个指定班次类型的班次)
  828 + */
  829 + public ScheduleRealInfo nextByBcType(String nbbm, String bcType) {
  830 + List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
  831 +
  832 + Collections.sort(list, schFCSJComparator);
  833 + ScheduleRealInfo sch = null;
  834 + for (ScheduleRealInfo temp : list) {
  835 + if (temp.getFcsjActual() == null) {
  836 + sch = temp;
  837 + break;
  838 + }
  839 + }
  840 +
  841 + return sch;
  842 + }
  843 +
  844 +
  845 + /**
  846 + * 搜索离当前时间最近的一个指定类型的班次
  847 + *
  848 + * @param nbbm
  849 + * @param bcType
  850 + * @return
  851 + */
  852 + public ScheduleRealInfo searchNearByBcType(String nbbm, String bcType) {
  853 + List<ScheduleRealInfo> list = findByBcType(nbbm, bcType);
  854 + Collections.sort(list, schFCSJComparator);
  855 +
  856 + long t = System.currentTimeMillis();
  857 + int distance = -1, diff;
  858 +
  859 + ScheduleRealInfo sch = null;
  860 + for (ScheduleRealInfo temp : list) {
  861 + diff = (int) Math.abs(temp.getDfsjT() - t);
  862 + if (diff < distance || distance == -1) {
  863 + sch = temp;
  864 + distance = diff;
  865 + }
  866 + }
  867 + return sch;
  868 + }
  869 +
  870 + public List<ScheduleRealInfo> findByBcType(String nbbm, String bcType) {
  871 + List<ScheduleRealInfo> all = nbbmScheduleMap.get(nbbm), outList = new ArrayList<>();
  872 +
  873 + for (ScheduleRealInfo sch : all) {
  874 + if (sch.getBcType().equals(bcType))
  875 + outList.add(sch);
  876 + }
  877 + return outList;
  878 + }
  879 +
  880 + public Collection<ScheduleRealInfo> findAll() {
  881 + return nbbmScheduleMap.values();
  882 + }
  883 +
  884 + public Collection<ScheduleRealInfo> findAllByLpContainer() {
  885 + return lpScheduleMap.values();
  886 + }
  887 +
  888 + public Collection<ScheduleRealInfo> findAllByIdContainer() {
  889 + return id2SchedulMap.values();
  890 + }
  891 +
  892 + public int getPstSize() {
  893 + return pstBuffer.size();
  894 + }
  895 +
  896 + public boolean addExecPlan(ScheduleRealInfo sch) {
  897 + ScheduleRealInfo oldExec = executeCurr(sch.getClZbh());
  898 + if (sch != null){
  899 + if(sch.getStatus()==2)
  900 + reCalcExecPlan(sch.getClZbh());
  901 + else
  902 + carExecutePlanMap.put(sch.getClZbh(), sch);
  903 + }
  904 + else
  905 + carExecutePlanMap.remove(sch.getClZbh());
  906 +
  907 + // rfid需要在新的执行班次前复位
  908 + RfidDataHandler.resetRfid(sch.getClZbh());
  909 +
  910 + return executeCurr(sch.getClZbh()) != oldExec;
  911 + }
  912 +
  913 + public void removeExecPlan(String clzbh) {
  914 + carExecutePlanMap.remove(clzbh);
  915 + }
  916 +
  917 + public Map<String, ScheduleRealInfo> execPlanMap() {
  918 + return carExecutePlanMap;
  919 + }
  920 +
  921 + /**
  922 + * 车辆当前执行的班次
  923 + *
  924 + * @param nbbm
  925 + * @return
  926 + */
  927 + public ScheduleRealInfo executeCurr(String nbbm) {
  928 + if(StringUtils.isEmpty(nbbm))
  929 + return null;
  930 + return carExecutePlanMap.get(nbbm);
  931 + }
  932 +
  933 + /**
  934 + * @param @param sch
  935 + * @param @param newClZbh 新的车辆自编号
  936 + * @Title: changeCar
  937 + * @Description: TODO(班次换车) 返回有更新的班次
  938 + */
  939 + public List<ScheduleRealInfo> changeCar(ScheduleRealInfo sch, String newClZbh) {
  940 + List<ScheduleRealInfo> ups = new ArrayList<>();
  941 +
  942 + String oldClZbh = sch.getClZbh();
  943 + //变更相关映射信息
  944 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  945 +
  946 + sch.setClZbh(newClZbh);
  947 + if (!nbbmScheduleMap.containsEntry(newClZbh, sch)) {
  948 + nbbmScheduleMap.put(newClZbh, sch);
  949 + }
  950 +
  951 + //重新计算车辆当前执行班次
  952 + reCalcExecPlan(newClZbh);
  953 + reCalcExecPlan(oldClZbh);
  954 + //重新分组计划用车
  955 + reCalcLineNbbms();
  956 + return ups;
  957 + }
  958 +
  959 + public void removeNbbm2SchMapp(ScheduleRealInfo sch) {
  960 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  961 + }
  962 +
  963 + public void addNbbm2SchMapp(ScheduleRealInfo sch) {
  964 + nbbmScheduleMap.put(sch.getClZbh(), sch);
  965 + }
  966 +
  967 + public void reCalcExecPlan(String nbbm) {
  968 + List<ScheduleRealInfo> list = nbbmScheduleMap.get(nbbm);
  969 + Collections.sort(list, schDFSJComparator);
  970 +
  971 + ScheduleRealInfo sch = schAttrCalculator.calcCurrentExecSch(list);
  972 + if(null != sch)
  973 + carExecutePlanMap.put(nbbm, sch);
  974 + else
  975 + carExecutePlanMap.remove(nbbm);
  976 + }
  977 +
  978 + /**
  979 + * 空驶任务?
  980 + * 出场、进场、直放、两点间空驶
  981 + * @param sch
  982 + * @return
  983 + */
  984 + public static boolean emptyService(ScheduleRealInfo sch){
  985 + String type = sch.getBcType();
  986 + return type.equals("out") || type.equals("in") || type.equals("venting") || type.equals("ldks");
  987 + }
  988 +
  989 + @Autowired
  990 + JdbcTemplate jdbcTemplate;
  991 +
  992 + /**
  993 + * 删除实际排班
  994 + *
  995 + * @param lineCode
  996 + * @return
  997 + */
  998 + public Map<String, Object> deleteRealSchedule(String lineCode) {
  999 + Map<String, Object> rs = new HashMap<>();
  1000 +
  1001 + try {
  1002 + String rq = currSchDateMap.get(lineCode);
  1003 + if (StringUtils.isNotEmpty(rq)) {
  1004 + List<ScheduleRealInfo> all = findByLineCode(lineCode);
  1005 +
  1006 + if(null != all && all.size() > 0){
  1007 + //解除gps 和班次之间的关联
  1008 + List<ScheduleRealInfo> unions = calcUnion(all, carExecutePlanMap.values());
  1009 + for (ScheduleRealInfo sch : unions) {
  1010 + removeExecPlan(sch.getClZbh());
  1011 + }
  1012 + //解除调度指令和班次的外键约束
  1013 + StringBuilder inStr = new StringBuilder("(");
  1014 + for (ScheduleRealInfo sch : all) {
  1015 + inStr.append(sch.getId() + ",");
  1016 + }
  1017 + inStr.deleteCharAt(inStr.length() - 1).append(")");
  1018 + jdbcTemplate.update(Constants.MULTI_REMOVE_DIRECTIVE_SCH_FK + " " + inStr.toString());
  1019 + }
  1020 +
  1021 + //删除班次数据
  1022 + removeRealSch(lineCode, rq);
  1023 +
  1024 + }
  1025 + rs.put("status", ResponseCode.SUCCESS);
  1026 + } catch (Exception e) {
  1027 + logger.error("", e);
  1028 + rs.put("status", ResponseCode.ERROR);
  1029 + if (e instanceof DataIntegrityViolationException)
  1030 + rs.put("msg", "失败,违反数据约束!!");
  1031 + else
  1032 + rs.put("msg", e.getMessage());
  1033 + }
  1034 +
  1035 + return rs;
  1036 + }
  1037 +
  1038 + /**
  1039 + * 计算并集
  1040 + *
  1041 + * @param c1
  1042 + * @param c2
  1043 + * @return
  1044 + */
  1045 + public List<ScheduleRealInfo> calcUnion(Collection<ScheduleRealInfo> c1, Collection<ScheduleRealInfo> c2) {
  1046 + List<ScheduleRealInfo> rs = new ArrayList<>();
  1047 +
  1048 + for (ScheduleRealInfo sch : c1) {
  1049 + if (c2.contains(sch)) {
  1050 + rs.add(sch);
  1051 + }
  1052 + }
  1053 + return rs;
  1054 + }
  1055 +
  1056 + /**
  1057 + * 覆盖一辆车的所有班次
  1058 + *
  1059 + * @param nbbm
  1060 + * @param sets
  1061 + */
  1062 + public void replaceByNbbm(String nbbm, Collection<ScheduleRealInfo> sets) {
  1063 + nbbmScheduleMap.removeAll(nbbm);
  1064 + nbbmScheduleMap.putAll(nbbm, sets);
  1065 + }
  1066 +
  1067 + /**
  1068 + * 获取该班次所在路牌的下一个班次
  1069 + *
  1070 + * @param sch
  1071 + * @return
  1072 + */
  1073 + public ScheduleRealInfo nextByLp(ScheduleRealInfo sch) {
  1074 + List<ScheduleRealInfo> list = lpScheduleMap.get(sch.getXlBm() + "_" + sch.getLpName());
  1075 + Collections.sort(list, schFCSJComparator);
  1076 + return next3_lp(list, sch);
  1077 + }
  1078 +
  1079 + /**
  1080 + * 获取该班次所在路牌的下一个班次,不考虑场既是站
  1081 + *
  1082 + * @param sch
  1083 + * @return
  1084 + */
  1085 + public ScheduleRealInfo nextByLp2(ScheduleRealInfo sch) {
  1086 + List<ScheduleRealInfo> list = lpScheduleMap.get(sch.getXlBm() + "_" + sch.getLpName());
  1087 + Collections.sort(list, schFCSJComparator);
  1088 + return next2_lp(list, sch);
  1089 + }
  1090 +
  1091 + public ArrayListMultimap<String, ScheduleRealInfo> getLpScheduleMap() {
  1092 + return lpScheduleMap;
  1093 + }
  1094 +
  1095 + /**
  1096 + * 重新全量计算路牌下的班次关联性
  1097 + * 临时性的函数
  1098 + */
  1099 + public void _test_reCalcLpSch() {
  1100 + Map<String ,Collection<ScheduleRealInfo>> map = lpScheduleMap.asMap();
  1101 + Set<String> ks = map.keySet();
  1102 + for(String k : ks){
  1103 + schAttrCalculator.calcQdzTimePlan(new ArrayList<ScheduleRealInfo>(map.get(k)));
  1104 + }
  1105 + }
  1106 +
  1107 + public int dbCount(String lineCode, String currSchDate) {
  1108 + int count = -1;
  1109 +
  1110 + try{
  1111 + count = jdbcTemplate.queryForObject("select count(*) from bsth_c_s_sp_info_real where schedule_date='"+currSchDate+"' and xl_bm='"+lineCode+"'", java.lang.Integer.class);
  1112 +
  1113 + }catch (Exception e){
  1114 + logger.error("", e);
  1115 + }
  1116 + return count;
  1117 + }
  1118 +
  1119 + /**
  1120 + * 重新计算ID对照map
  1121 + */
  1122 + public int reCalcIdMaps(){
  1123 + Collection<ScheduleRealInfo> all = findAll();
  1124 + ConcurrentMap<Long, ScheduleRealInfo> id2SchedulMapCopy = new ConcurrentHashMap<>();
  1125 +
  1126 + for(ScheduleRealInfo sch : all){
  1127 + id2SchedulMapCopy.put(sch.getId(), sch);
  1128 + }
  1129 +
  1130 + id2SchedulMap = id2SchedulMapCopy;
  1131 +
  1132 + return id2SchedulMap.size();
  1133 + }
  1134 +
  1135 + /**
  1136 + * 重新计算线路计划用车
  1137 + */
  1138 + public void reCalcLineNbbms(){
  1139 + HashMultimap<String, String> multimap = HashMultimap.create();
  1140 +
  1141 + Collection<ScheduleRealInfo> schs = nbbmScheduleMap.values();
  1142 + for (ScheduleRealInfo sch : schs) {
  1143 + multimap.put(sch.getXlBm(), sch.getClZbh());
  1144 + }
  1145 +
  1146 + lineNbbmsMap = multimap;
  1147 + }
  1148 +
  1149 + public String sizeString(){
  1150 + return id2SchedulMap.size() + "/" + nbbmScheduleMap.size();
  1151 + }
  1152 +
  1153 +
  1154 + /**
  1155 + * 按公司编码分组数据
  1156 + */
  1157 + public void groupByGsbm(){
  1158 + Collection<ScheduleRealInfo> all = findAll();
  1159 + ListMultimap<String, ScheduleRealInfo> gsBmMaps = ArrayListMultimap.create();
  1160 +
  1161 + for(ScheduleRealInfo sch : all){
  1162 + gsBmMaps.put(sch.getGsBm(), sch);
  1163 + }
  1164 +
  1165 + if(gsBmMaps.size() > 0){
  1166 + gsBmScheduleMap = null;
  1167 + gsBmScheduleMap = gsBmMaps;
  1168 + }
  1169 + }
  1170 +
  1171 + public Collection<ScheduleRealInfo> findByGsbm(String gsbm){
  1172 + return gsBmScheduleMap.get(gsbm);
  1173 + }
  1174 + /**
  1175 + * 删除班次,删除内存中未清理掉的非当天的班次
  1176 + * @createDate 2019.05.13
  1177 + * @author zhangxianzhou
  1178 + * @param sch
  1179 + */
  1180 + public void deleteBC(ScheduleRealInfo sch) {
  1181 + nbbmScheduleMap.remove(sch.getClZbh(), sch);
  1182 + id2SchedulMap.remove(sch.getId());
  1183 + lpScheduleMap.remove(sch.getXlBm() + "_" + sch.getLpName(), sch);
  1184 + //如果正在执行该班次
  1185 + if (carExecutePlanMap.get(sch.getClZbh()) == sch) {
  1186 + //重新计算车辆当前执行班次
  1187 + reCalcExecPlan(sch.getClZbh());
  1188 + }
  1189 + }
  1190 +
  1191 + /**
  1192 + ** 用于重置维修上报计数,一般只应该在翻班的时候调用
  1193 + */
  1194 + public void resetRepairReport(String incode) {
  1195 + incode2report.remove(incode);
  1196 + }
  1197 +
  1198 + public RepairReport getLastestRepairReport(String incode) {
  1199 + return incode2report.get(incode);
  1200 + }
  1201 +
  1202 + public void setLastestRepairReport(RepairReport rr) {
  1203 + incode2report.put(rr.getIncode(), rr);
  1204 + }
1201 1205 }
1202 1206 \ No newline at end of file
... ...
src/main/resources/static/real_control_v2/css/line_schedule.css
... ... @@ -935,7 +935,7 @@ input.i-cbox[type=checkbox]{
935 935  
936 936 .tl-tip-panel .ct_title{
937 937 display: inline-block;
938   - width: 42px;
  938 + width: 82px;
939 939 vertical-align: top;
940 940 margin-top: 5px;
941 941 color: grey;
... ... @@ -954,7 +954,7 @@ input.i-cbox[type=checkbox]{
954 954 }
955 955  
956 956 .qtip.sch-tl-tip{
957   - max-width: 335px;
  957 + max-width: 380px;
958 958 }
959 959  
960 960 .sfsj-sch-detail{
... ...
src/main/resources/static/real_control_v2/fragments/line_schedule/layout.html
1   -<div>
2   - <!-- line schedule tab body layout template -->
3   - <script id="cont-line-layout-temp" type="text/html">
4   - <div class="uk-grid top-container">
5   - <div class="uk-width-5-6 uk-grid schedule-wrap">
6   - <div class="uk-width-1-2">
7   - <div class="card-panel"></div>
8   - </div>
9   -
10   - <div class="uk-width-1-2">
11   - <div class="card-panel"></div>
12   - </div>
13   - </div>
14   - <div class="uk-width-1-6" style="height: calc(100% - 1px);position: relative;">
15   - <div class="card-panel sys-mailbox" style="overflow: auto;">
16   - </div>
17   - <div class="mileage_elec_panel">
18   - </div>
19   - </div>
20   - </div>
21   -
22   - <div class="footer-chart">
23   - <div class="card-panel">
24   - <div class="svg-wrap"></div>
25   - </div>
26   - </div>
27   - </script>
28   -
29   - <script id="sch-table-top-help-temp" type="text/html">
30   - <div class="tl-tip-panel">
31   - <div class="ct_title">
32   - 图例
33   - </div>
34   - <div style="display: inline-block;width: calc(100% - 50px)">
35   - <span class="tl-wd">误点</span>
36   - <span class="tl-zzzx">正在执行</span>
37   - <span class="tl-qrlb"></span>
38   - <span class="tl-yzx">已执行</span>
39   - <span class="tl-xxfc">消息发出</span>
40   - <span class="tl-xxsd">消息收到</span>
41   - <span class="tl-xxrd">消息阅读</span>
42   - <span class="tl-wfyd">无发有到</span>
43   - </div>
44   - </div>
45   - </script>
46   -
47   - <script id="sch-table-m_station_error-temp" type="text/html">
48   - <div class="tl-tip-panel">
49   - <ul class="uk-list uk-list-line" style="margin-bottom: 0;">
50   - {{each list as obj i}}
51   - {{if obj.realStationCode!=null}}
52   - <li>【{{obj.stationName}}】班次用的站点 <span style="color: red;">{{obj.stationCode}}</span> -实际:{{obj.realStationCode}}</li>
53   - {{else}}
54   - <li>【{{obj.stationName}}】班次用的站点 <span style="color: red;">{{obj.stationCode}}</span> -在站点路由中不存在的</li>
55   - {{/if}}
56   - {{/each}}
57   -
58   - </ul>
59   - </div>
60   - </script>
61   -</div>
  1 +<div>
  2 + <!-- line schedule tab body layout template -->
  3 + <script id="cont-line-layout-temp" type="text/html">
  4 + <div class="uk-grid top-container">
  5 + <div class="uk-width-5-6 uk-grid schedule-wrap">
  6 + <div class="uk-width-1-2">
  7 + <div class="card-panel"></div>
  8 + </div>
  9 +
  10 + <div class="uk-width-1-2">
  11 + <div class="card-panel"></div>
  12 + </div>
  13 + </div>
  14 + <div class="uk-width-1-6" style="height: calc(100% - 1px);position: relative;">
  15 + <div class="card-panel sys-mailbox" style="overflow: auto;">
  16 + </div>
  17 + <div class="mileage_elec_panel">
  18 + </div>
  19 + </div>
  20 + </div>
  21 +
  22 + <div class="footer-chart">
  23 + <div class="card-panel">
  24 + <div class="svg-wrap"></div>
  25 + </div>
  26 + </div>
  27 + </script>
  28 +
  29 + <script id="sch-table-top-help-temp" type="text/html">
  30 + <div class="tl-tip-panel">
  31 + <div class="ct_title">
  32 + 图例(班次)
  33 + </div>
  34 + <div style="display: inline-block;width: calc(100% - 90px)">
  35 + <span class="tl-wd">误点</span>
  36 + <span class="tl-zzzx">正在执行</span>
  37 + <span class="tl-qrlb"></span>
  38 + <span class="tl-yzx">已执行</span>
  39 + <span class="tl-xxfc">消息发出</span>
  40 + <span class="tl-xxsd">消息收到</span>
  41 + <span class="tl-xxrd">消息阅读</span>
  42 + <span class="tl-wfyd">无发有到</span>
  43 + </div>
  44 + <div class="ct_title">
  45 + 图例(RFID)
  46 + </div>
  47 + <div style="display: inline-block;width: calc(100% - 90px)">
  48 + <span class="tl-green" style="color: black">有车人卡</span>
  49 + <span class="tl-yellow" style="color: black">有车卡</span>
  50 + <span class="tl-grey" style="color: black">无车人卡</span>
  51 + </div>
  52 + </div>
  53 + </script>
  54 +
  55 + <script id="sch-table-m_station_error-temp" type="text/html">
  56 + <div class="tl-tip-panel">
  57 + <ul class="uk-list uk-list-line" style="margin-bottom: 0;">
  58 + {{each list as obj i}}
  59 + {{if obj.realStationCode!=null}}
  60 + <li>【{{obj.stationName}}】班次用的站点 <span style="color: red;">{{obj.stationCode}}</span> -实际:{{obj.realStationCode}}</li>
  61 + {{else}}
  62 + <li>【{{obj.stationName}}】班次用的站点 <span style="color: red;">{{obj.stationCode}}</span> -在站点路由中不存在的</li>
  63 + {{/if}}
  64 + {{/each}}
  65 +
  66 + </ul>
  67 + </div>
  68 + </script>
  69 +</div>
... ...