Commit 12665bca2c6f42adcd87bedb8809c75bbfc13753

Authored by 徐烜
1 parent e1790793

时刻表v2.6

1、中标线可以和上标线在同一个路牌上,就是两个方向的首班车同一辆车开
2、给班次对象添加是否首末班的标识,在调整路牌班次横向间隔的时候需要过滤首班车次
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalBcObj.js
... ... @@ -42,10 +42,28 @@ var InternalBcObj = function(
42 42 // 标记参数,这个班次用于计算,最后必须删除
43 43 this._$_bDelFlag = false;
44 44  
  45 + // 是否首末站
  46 + this._$_bIsFirstBc = false;
  47 + this._$_bIsLastBc = false;
  48 +
45 49 };
46 50  
47 51 //------------------- get/set 方法 -------------------//
48 52  
  53 +InternalBcObj.prototype.fnSetIsFirstBc = function(bFlag) {
  54 + this._$_bIsFirstBc = true;
  55 +};
  56 +InternalBcObj.prototype.fnIsFirstBc = function() {
  57 + return this._$_bIsFirstBc;
  58 +};
  59 +
  60 +InternalBcObj.prototype.fnSetIsLastBc = function(bFlag) {
  61 + this._$_bIsLastBc = bFlag;
  62 +};
  63 +InternalBcObj.prototype.fnIsLastBc = function() {
  64 + return this._$_bIsLastBc;
  65 +};
  66 +
49 67 InternalBcObj.prototype.fnSetEatTime = function(iTime) {
50 68 this._$_iEatTime = iTime;
51 69 };
... ...
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalLpObj.js
1   -/**
2   - * 内部路牌对象。
3   - * @constructor
4   - */
5   -var InternalLpObj = function(
6   - orilpObj, // 原始路牌对象
7   - qCount, // 总共多少圈
8   - isUp // 圈是以上行开始还是下行开始
9   -) {
10   - // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
11   - this._$$_orign_lp_obj = orilpObj;
12   -
13   - this._$_isUp = isUp;
14   -
15   - // 路牌的圈数,注意每个路牌的圈数都是一致的,
16   - // 但并不是每一圈都有值
17   - // 第1圈从上标线开始
18   - // 第0圈表示中标线的第一个班次组成的半圈
19   - // 有多少圈根据最终迭代的结果来看
20   - this._$_qCount = qCount;
21   - // 保存的是 InternalGroupBcObj 对象
22   - this._$_groupBcArray = new Array(qCount);
23   -
24   - var i;
25   - for (i = 0; i < this._$_qCount; i++) {
26   - this._$_groupBcArray[i] = new InternalGroupObj(
27   - this, this._$_isUp, undefined, undefined);
28   - }
29   -
30   - // 距离上一个路牌的最小发车间隔时间
31   - // 用于纵向添加班次的时候使用
32   - // 默认第一个路牌为0
33   - this._$_minVerticalIntervalTime = 0;
34   -
35   - // 详细记录每圈每个方向上的发车间隔时间
36   - // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
37   - // 第一个方向是否上行由 _$_isUp 决定
38   - // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
39   - // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
40   - this._$_aVerticalIntervalTime = new Array(this._$_qCount);
41   - var i;
42   - for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
43   - this._$_aVerticalIntervalTime[i] = new Array(2);
44   - }
45   -
46   - // 班型的相关变量
47   - this._$_bx_isLb = false; // 是否连班
48   - this._$_bx_isfb = false; // 是否分班
49   - this._$_bx_isfb_5_2 = false; // 是否5休2分班
50   - this._$_bx_desc; // 班型描述(默认为路牌编号)
51   -
52   - // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
53   - this._$_other_bc_array = [];
54   -
55   - // TODO:
56   -
57   -};
58   -
59   -//------------------- get/set 方法 -------------------//
60   -
61   -InternalLpObj.prototype.getOtherBcArray = function() {
62   - return this._$_other_bc_array;
63   -};
64   -InternalLpObj.prototype.addOtherBcArray = function(ba) {
65   - this._$_other_bc_array = this._$_other_bc_array.concat(ba);
66   -};
67   -
68   -/**
69   - * 获取圈
70   - * @param qIndex 圈index
71   - */
72   -InternalLpObj.prototype.getGroup = function(qIndex) {
73   - return this._$_groupBcArray[qIndex];
74   -};
75   -
76   -/**
77   - * 获取班次。
78   - * @param qIndex 第几圈
79   - * @param bcIndex 第几个班次
80   - */
81   -InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
82   - var group = this._$_groupBcArray[qIndex];
83   - var bc;
84   - if (bcIndex == 0) {
85   - bc = group.getBc1();
86   - } else if (bcIndex == 1) {
87   - bc = group.getBc2();
88   - }
89   - return bc;
90   -};
91   -
92   -/**
93   - * 在具体位置设置班次。
94   - * @param qIndex 第几圈
95   - * @param bcIndex 第几个班次
96   - * @param bc 班次对象
97   - */
98   -InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
99   - var group = this._$_groupBcArray[qIndex];
100   - if (bcIndex == 0) {
101   - group.setBc1(bc);
102   - bc.setGroup(group);
103   - } else if (bcIndex == 1) {
104   - group.setBc2(bc);
105   - bc.setGroup(group);
106   - }
107   -};
108   -
109   -/**
110   - * 设置原始路牌对象。
111   - * @param lpObj 原始路牌对象
112   - */
113   -InternalLpObj.prototype.setLp = function(lpObj) {
114   - this._$$_orign_lp_obj = lpObj;
115   - var i;
116   - var group;
117   - for (i = 0; i < this._$_groupBcArray.length; i++) {
118   - group = this._$_groupBcArray[i];
119   - if (group) {
120   - group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
121   - }
122   - }
123   -};
124   -
125   -InternalLpObj.prototype.getLpNo = function() {
126   - return this._$$_orign_lp_obj.lpNo;
127   -};
128   -InternalLpObj.prototype.getLpName = function() {
129   - return this._$$_orign_lp_obj.lpName;
130   -};
131   -InternalLpObj.prototype.setBxFb5_2 = function(fb) {
132   - this._$_bx_isfb_5_2 = fb;
133   -};
134   -InternalLpObj.prototype.isBxFb5_2 = function() {
135   - return this._$_bx_isfb_5_2;
136   -};
137   -InternalLpObj.prototype.setBxLb = function(lb) {
138   - this._$_bx_isLb = lb;
139   -};
140   -InternalLpObj.prototype.isBxLb = function() {
141   - return this._$_bx_isLb;
142   -};
143   -
144   -InternalLpObj.prototype.setBxFb = function(fb) {
145   - this._$_bx_isfb = fb;
146   -};
147   -InternalLpObj.prototype.isBxFb = function() {
148   - return this._$_bx_isfb;
149   -};
150   -
151   -/**
152   - * 设置路牌的班型描述(最终是设置班次的路牌名字)。
153   - * @param desc 描述
154   - */
155   -InternalLpObj.prototype.setBxDesc = function(desc) {
156   - // 最终原始路牌的名字
157   - this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
158   - // 内部对象的班型描述
159   - this._$_bx_desc = desc;
160   -};
161   -/**
162   - * 获取版型描述
163   - * @returns string
164   - */
165   -InternalLpObj.prototype.getBxDesc = function() {
166   - return this._$_bx_desc;
167   -};
168   -
169   -/**
170   - * 设置纵向最小发车间隔时间。
171   - * @param v
172   - */
173   -InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
174   - // 第一个路牌,都为0
175   - this._$_minVerticalIntervalTime = v;
176   -};
177   -/**
178   - * 获取纵向最小发车间隔时间。
179   - * @returns {number|*}
180   - */
181   -InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
182   - return this._$_minVerticalIntervalTime;
183   -};
184   -
185   -/**
186   - * 设置纵向发车间隔。
187   - * @param iQindex 圈index
188   - * @param iBindex 班次index
189   - * @param iTime 间隔时间
190   - */
191   -InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
192   - this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
193   -};
194   -
195   -/**
196   - * 返回纵向发车间隔。
197   - * @param iQindex 圈index
198   - * @param iBindex 班次index
199   - */
200   -InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
201   - return this._$_aVerticalIntervalTime[iQindex][iBindex];
202   -};
203   -
204   -//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
205   -
206   -/**
207   - * 返回总共班次数。
208   - */
209   -InternalLpObj.prototype.getBcCount = function() {
210   - var i;
211   - var group;
212   - var bccount = 0;
213   - for (i = 0; i < this._$_groupBcArray.length; i++) {
214   - group = this._$_groupBcArray[i];
215   - if (group) {
216   - if (group.getBc1()) {
217   - bccount += 1;
218   - }
219   - if (group.getBc2()) {
220   - bccount += 1;
221   - }
222   - }
223   - }
224   -
225   - return bccount;
226   -};
227   -
228   -/**
229   - * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
230   - * @returns arrays (InternalBcObj)
231   - */
232   -InternalLpObj.prototype.getBcArray = function() {
233   - var bcArray = [];
234   - var i;
235   - var group;
236   - for (i = 0; i < this._$_groupBcArray.length; i++) {
237   - group = this._$_groupBcArray[i];
238   - if (group) {
239   - group.getBc1() ? bcArray.push(group.getBc1()) : "";
240   - group.getBc2() ? bcArray.push(group.getBc2()) : "";
241   - }
242   - }
243   -
244   - return bcArray;
245   -};
246   -
247   -/**
248   - * 获取最小(最早)班次对象。
249   - * @returns [{圈index},{班次index}]
250   - */
251   -InternalLpObj.prototype.getMinBcObjPosition = function() {
252   - var i;
253   - var bIndex = [];
254   - for (i = 0; i < this._$_groupBcArray.length; i++) {
255   - if (this._$_groupBcArray[i].getBc1()) {
256   - bIndex.push(i);
257   - bIndex.push(0);
258   - break;
259   - }
260   - if (this._$_groupBcArray[i].getBc2()) {
261   - bIndex.push(i);
262   - bIndex.push(1);
263   - break;
264   - }
265   - }
266   - return bIndex;
267   -};
268   -
269   -/**
270   - * 获取最大(最晚)班次对象。
271   - * @returns [{圈index},{班次index}]
272   - */
273   -InternalLpObj.prototype.getMaxBcObjPosition = function() {
274   - var i;
275   - var bIndex = [];
276   - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
277   - if (this._$_groupBcArray[i].getBc2()) {
278   - bIndex.push(i);
279   - bIndex.push(1);
280   - break;
281   - }
282   - if (this._$_groupBcArray[i].getBc1()) {
283   - bIndex.push(i);
284   - bIndex.push(0);
285   - break;
286   - }
287   - }
288   - return bIndex;
289   -};
290   -
291   -InternalLpObj.prototype.getMinBcObj = function() {
292   - var i;
293   - var bcObj;
294   - for (i = 0; i < this._$_groupBcArray.length; i++) {
295   - bcObj = this._$_groupBcArray[i].getBc1();
296   - if (bcObj) {
297   - break;
298   - }
299   - bcObj = this._$_groupBcArray[i].getBc2();
300   - if (bcObj) {
301   - break;
302   - }
303   - }
304   - return bcObj;
305   -};
306   -InternalLpObj.prototype.getMaxBcObj = function() {
307   - var i;
308   - var bcObj;
309   - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
310   - bcObj = this._$_groupBcArray[i].getBc2();
311   - if (bcObj) {
312   - break;
313   - }
314   - bcObj = this._$_groupBcArray[i].getBc1();
315   - if (bcObj) {
316   - break;
317   - }
318   - }
319   - return bcObj;
320   -};
321   -
322   -/**
323   - * 获取车次链信息。
324   - * @param num 第几个车次链
325   - * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
326   - */
327   -InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
328   - // 计算总的车次链信息
329   - var aChainInfo = [];
330   - var oChainInfo;
331   - var aBcIndex = this.getMinBcObjPosition();
332   - var oBc;
333   - var iQIndex;
334   - var iBcIndex;
335   - var i;
336   - var bFlag;
337   -
338   - var iBcount = 0;
339   -
340   - if (aBcIndex.length == 2) {
341   - iBcount = 1;
342   - oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
343   - aChainInfo.push(oChainInfo);
344   - bFlag = true;
345   -
346   - // 下一个班次的索引
347   - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
348   - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
349   -
350   - for (i = iQIndex; i < this._$_qCount; i++) {
351   - while (iBcIndex <= 1) {
352   - oBc = this.getBc(i, iBcIndex);
353   - if (!oBc) {
354   - if (bFlag) {
355   - // 车次链结尾是这个班次的前一个班次
356   - oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
357   - oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
358   - oChainInfo.bcount = iBcount;
359   - }
360   -
361   - bFlag = false;
362   - } else {
363   - if (bFlag) {
364   - iBcount ++;
365   - oChainInfo.bcount = iBcount;
366   - } else {
367   - // 下一个车次链开始
368   - iBcount = 1;
369   - oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
370   - aChainInfo.push(oChainInfo);
371   - bFlag = true;
372   - }
373   - }
374   -
375   -
376   - iBcIndex ++;
377   - }
378   - iBcIndex = 0;
379   - }
380   -
381   - }
382   -
383   - return aChainInfo[num];
384   -};
385   -
386   -/**
387   - * 获取车次链的个数。
388   - * @returns int
389   - */
390   -InternalLpObj.prototype.fnGetBcChainCount = function() {
391   - var iChainCount = 0;
392   - var aBcIndex = this.getMinBcObjPosition();
393   -
394   - var oBc;
395   - var iQIndex;
396   - var iBcIndex;
397   - var i;
398   - var bFlag;
399   -
400   - if (aBcIndex.length == 2) {
401   - iChainCount = 1;
402   - bFlag = true;
403   -
404   - // 下一个班次的索引
405   - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
406   - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
407   -
408   - for (i = iQIndex; i < this._$_qCount; i++) {
409   - while (iBcIndex <= 1) {
410   - oBc = this.getBc(i, iBcIndex);
411   - if (!oBc) {
412   - bFlag = false;
413   - } else {
414   - if (bFlag) {
415   -
416   - } else {
417   - iChainCount ++;
418   - bFlag = true;
419   - }
420   - }
421   -
422   -
423   - iBcIndex ++;
424   - }
425   - iBcIndex = 0;
426   - }
427   -
428   - }
429   -
430   -
431   - return iChainCount;
432   -};
433   -
434   -/**
435   - * 在具体位置移除班次。
436   - * @param qIndex 第几圈
437   - * @param bcIndex 第几个班次
438   - */
439   -InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
440   - var group = this._$_groupBcArray[qIndex];
441   - if (bcIndex == 0) {
442   - group.removeBc1();
443   - } else if (bcIndex == 1) {
444   - group.removeBc2();
445   - }
446   -};
447   -
448   -/**
449   - * 使用指定时间匹配返回离之最近的第几圈第几个班次,
450   - * 使用时间差的绝度值,比较,取最小的
451   - * 如果有两个一样的时间差,取比fctime大的时间
452   - * @param fctime moment 比较用时间
453   - * @param groupArray 圈数组
454   - * @param hasUp boolean 计算上行班次
455   - * @param hasDown boolean 计算下行班次
456   - * @returns [{第几圈},{第几个班次}]
457   - */
458   -InternalLpObj.prototype.getgetQBcIndexWithFcTimeFromGroupArray = function(
459   - fctime, groupArray, hasUp, hasDown
460   -) {
461   - var i;
462   - var timediff; // 时间差取绝对值
463   - var qIndex;
464   - var bcIndex;
465   -
466   - var group;
467   - var bc1time;
468   - var bc2time;
469   -
470   - var tempdiff;
471   - for (i = 0; i < this._$_qCount; i++) {
472   - group = groupArray[i];
473   - if (group) {
474   - if (group.getBc1() && hasUp) {
475   - bc1time = group.getBc1().getFcTimeObj();
476   - tempdiff = Math.abs(bc1time.diff(fctime));
477   -
478   - if (!timediff) {
479   - timediff = Math.abs(tempdiff);
480   - qIndex = i;
481   - bcIndex = 0;
482   - } else {
483   - if (tempdiff < timediff) {
484   - timediff = tempdiff;
485   - qIndex = i;
486   - bcIndex = 0;
487   - } if (Math.abs(tempdiff) == timediff) {
488   - if (bc1time.isBefore(fctime)) {
489   - timediff = tempdiff;
490   - qIndex = i;
491   - bcIndex = 0;
492   - }
493   -
494   - }
495   - }
496   - }
497   -
498   - if (group.getBc2() && hasDown) {
499   - bc2time = group.getBc2().getFcTimeObj();
500   - tempdiff = Math.abs(bc2time.diff(fctime));
501   -
502   - if (!timediff) {
503   - timediff = Math.abs(tempdiff);
504   - qIndex = i;
505   - bcIndex = 1;
506   - } else {
507   - if (tempdiff < timediff) {
508   - timediff = tempdiff;
509   - qIndex = i;
510   - bcIndex = 1;
511   - } if (Math.abs(tempdiff) == timediff) {
512   - if (bc2time.isBefore(fctime)) {
513   - timediff = tempdiff;
514   - qIndex = i;
515   - bcIndex = 1;
516   - }
517   -
518   - }
519   - }
520   - }
521   - }
522   - }
523   -
524   - var rst = [];
525   - rst.push(qIndex);
526   - rst.push(bcIndex);
527   -
528   - return rst;
529   -};
530   -
531   -/**
532   - * 使用指定时间匹配返回离之最近的第几圈第几个班次,
533   - * 使用时间差的绝度值,比较,取最小的
534   - * 如果有两个一样的时间差,取比fctime大的时间
535   - * @param fctime moment 比较用时间
536   - * @param hasUp boolean 计算上行班次
537   - * @param hasDown boolean 计算下行班次
538   - * @returns [{第几圈},{第几个班次}]
539   - */
540   -InternalLpObj.prototype.getQBcIndexWithFcTime = function(
541   - fctime, hasUp, hasDown
542   -) {
543   - return this.getgetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
544   -};
545   -
546   -//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
547   -
548   -/**
549   - * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
550   - * 注意,之前有班次会删除后再创建。
551   - * @param startTime 开始时间
552   - * @param endTime 结束时间
553   - * @param isUp 第一个班次是上行还是下行
554   - * @param fromQ 从第几圈开始加入
555   - * @param paramObj 参数对象
556   - * @param factory 工厂对象
557   - */
558   -InternalLpObj.prototype.initDataFromTimeToTime = function(
559   - startTime,
560   - endTime,
561   - isUp,
562   - fromQ,
563   - paramObj,
564   - factory) {
565   -
566   - var bcData = []; // 班次数组
567   - var bcObj;
568   - var kssj = startTime;
569   - var fcno = 1; // 发车顺序号
570   - var bcCount = 1; // 班次数
571   - do {
572   - bcObj = factory.createBcObj(
573   - this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
574   - bcData.push(bcObj);
575   -
576   - kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
577   - fcno ++;
578   - bcCount ++;
579   - isUp = !isUp;
580   - } while(kssj.isBefore(endTime));
581   - bcCount--;
582   -
583   - //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
584   - //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
585   - //console.log("endtime: " + endTime.format("HH:mm"));
586   -
587   - //if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
588   - // // 如果最后一个班次的到达时间超过结束时间,也要去除
589   - // bcData.splice(bcCount - 1, 1);
590   - //}
591   -
592   - this._initDataFromLbBcArray(bcData, fromQ);
593   -
594   -};
595   -
596   -/**
597   - * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
598   - * @param bcArray 连班班次数组
599   - * @param fromQ 从第几圈开始加入
600   - */
601   -InternalLpObj.prototype._initDataFromLbBcArray = function(
602   - bcArray,
603   - fromQ
604   -) {
605   - var _bc1Obj;
606   - var _bc2Obj;
607   - var _qObj;
608   -
609   - // 第一班次是上行还是下行
610   - var isUp = bcArray[0].isUp();
611   -
612   - if (bcArray.length > 0 && fromQ < this._$_qCount) {
613   - // 构造圈数
614   - if (isUp != this._$_isUp) {
615   - // 如果方向不一致,意味着第一个班次是半圈
616   - // 加半圈,并加在bc2上
617   - _bc2Obj = bcArray.slice(0, 1)[0];
618   - _qObj = new InternalGroupObj(
619   - this,
620   - this._$_isUp,
621   - undefined,
622   - _bc2Obj
623   - );
624   - _bc2Obj.setGroup(_qObj);
625   - this._$_groupBcArray[fromQ] = _qObj;
626   -
627   - bcArray.splice(0, 1);
628   - fromQ ++;
629   - }
630   -
631   - var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
632   - var qCount2 = bcArray.length % 2; // 最后是否有半圈
633   -
634   - while (fromQ < this._$_qCount) {
635   - if (qCount1 > 0) {
636   - _bc1Obj = bcArray.slice(0, 1)[0];
637   - _bc2Obj = bcArray.slice(1, 2)[0];
638   - _qObj = new InternalGroupObj(
639   - this,
640   - this._$_isUp,
641   - _bc1Obj,
642   - _bc2Obj
643   - );
644   - _bc1Obj.setGroup(_qObj);
645   - _bc2Obj.setGroup(_qObj);
646   - this._$_groupBcArray[fromQ] = _qObj;
647   -
648   - bcArray.splice(0, 2);
649   - qCount1 --;
650   - } else if (qCount2 > 0) {
651   - // 加半圈,并加在bc1上
652   - _bc1Obj = bcArray.slice(0, 1)[0];
653   - _qObj = new InternalGroupObj(
654   - this,
655   - this._$_isUp,
656   - _bc1Obj,
657   - undefined
658   - );
659   - _bc1Obj.setGroup(_qObj);
660   - this._$_groupBcArray[fromQ] = _qObj;
661   -
662   - bcArray.splice(0, 1);
663   - qCount2 --;
664   - } else {
665   - break;
666   - }
667   -
668   - fromQ ++;
669   - }
670   - }
671   -};
672   -
673   -//-------------------------- 其他方法 ----------------------------//
674   -
675   -/**
676   - * 从指定位置的班次开始,往后所有的班次修正发车时间
677   - * @param groupIndex
678   - * @param bcIndex
679   - * @param time
680   - */
681   -InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
682   - var i;
683   - var oCurBc;
684   -
685   - // 修正之前班次的停站时间
686   - //oCurBc = this.getBc(
687   - // bcIndex == 0 ? groupIndex - 1 : groupIndex,
688   - // bcIndex == 1 ? 0 : 1
689   - //);
690   - //if (oCurBc) {
691   - // oCurBc.setStopTime(oCurBc.getStopTime() + time);
692   - //}
693   -
694   -
695   - for (i = groupIndex; i < this._$_qCount; i++) {
696   - if (bcIndex == 0) {
697   - oCurBc = this.getBc(i, 0);
698   - if (oCurBc) {
699   - oCurBc.addMinuteToFcsj(time);
700   - }
701   - oCurBc = this.getBc(i, 1);
702   - if (oCurBc) {
703   - oCurBc.addMinuteToFcsj(time);
704   - }
705   -
706   - } else {
707   - oCurBc = this.getBc(i, 1);
708   - if (oCurBc) {
709   - oCurBc.addMinuteToFcsj(time);
710   - }
711   -
712   - }
713   -
714   - bcIndex = 0;
715   - }
716   -};
717   -
718   -/**
719   - * 在指定位置添加一个吃饭班次。
720   - * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
721   - * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
722   - * @param groupIndex
723   - * @param bcIndex
724   - * @param factory
725   - * @param paramObj
726   - * @returns int 相差时间(吃饭时间距离和停站时间相差值)
727   - */
728   -InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
729   - var oPreBc;
730   - var oEatBc;
731   - var iBcModifyTime;
732   - oPreBc = this.getBc( // 前一个邻接班次
733   - bcIndex == 0 ? groupIndex - 1 : groupIndex,
734   - bcIndex == 1 ? 0 : 1);
735   - if (oPreBc) { // 存在前一个班次
736   - oEatBc = factory.createBcObj(
737   - this,
738   - "cf",
739   - !oPreBc.isUp(), // 和上一个班次方向相反
740   - 1,
741   - paramObj.addMinute(oPreBc.getArrTimeObj(), oPreBc.getStopTime()), // 使用上一个班次的到达时间作为开始时间
742   - paramObj
743   - );
744   -
745   - //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间
746   -
747   - // 修正之后的班次发车时间
748   - // 注意:之后那个班次发车时间就是吃饭班次的到达时间
749   - iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");
750   - this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);
751   -
752   - oPreBc.setStopTime(0); // 不重置停站时间
753   - oPreBc.fnSetEatTime(oEatBc.getBcTime());
754   -
755   - //this._$_other_bc_array.push(oEatBc);
756   -
757   - return iBcModifyTime;
758   - } else {
759   - return false;
760   - }
761   -
762   -};
763   -
764   -/**
765   - * 调整路牌的班次,通过调整停站时间,或者班次发车时间,不能让班次的到达时间和下一个班次的发车时间重叠。
766   - * @param iPeakAverStopTime 高峰平均停站时间
767   - * @param iTroughAverStopTime 低谷平均停站时间
768   - * @param oParam 参数对象
769   - */
770   -InternalLpObj.prototype.fnAdjustBcInterval = function(iPeakAverStopTime, iTroughAverStopTime, oParam) {
771   - // 获取车次链个数
772   - var iBcChainCount = this.fnGetBcChainCount();
773   -
774   - var i;
775   - var j;
776   - var oBcIndex;
777   - var iQIndex;
778   - var iBcIndex;
779   - var iBcCount;
780   - var oBc;
781   - var oNextBc;
782   -
783   - var iBcStopTime;
784   -
785   - for (i = 0; i < iBcChainCount; i++) {
786   - oBcIndex = this.fnGetBcChainInfo(i);
787   - iQIndex = oBcIndex["s_q"];
788   - iBcIndex = oBcIndex["s_b"];
789   - iBcCount = oBcIndex["bcount"];
790   -
791   - for (j = 0; j < iBcCount - 1; j++) {
792   - oBc = this.getBc(iQIndex, iBcIndex);
793   - oNextBc = this.getBc(
794   - iBcIndex == 0 ? iQIndex : iQIndex + 1,
795   - iBcIndex == 0 ? 1 : 0);
796   -
797   - // 不改变当前班次的行驶时间,修正停站时间和下一个班次的发车时间
798   - iBcStopTime = oNextBc.getFcTimeObj().diff(oBc.getArrTimeObj(), "m");
799   - if (iBcStopTime < 0) {
800   - // 当前班次使用最小停站时间
801   - oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
802   - oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
803   -
804   - } else {
805   - if (iBcStopTime == oBc.getStopTime() + oBc.fnGetEatTime()) {
806   - // 停站时间一致,没有问题
807   -
808   -
809   - } else {
810   - // TODO:当前班次使用最小停站时间
811   - oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
812   - oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
813   -
814   - }
815   - }
816   -
817   - iBcIndex = iBcIndex == 0 ? 1 : 0;
818   - iQIndex = iBcIndex == 0 ? iQIndex + 1 : iQIndex;
819   - }
820   -
821   - this.getBc(iQIndex, iBcIndex).setStopTime(0);
822   - }
823   -
824   -
825   -};
826   -
827   -
828   -// TODO
829   -
830   -/**
831   - *
832   - *
833   - */
834   -InternalLpObj.prototype.calcuLpBx = function() {
835   -
836   -};
837   -
838   -
839   -
840   -
841   -
842   -
843   -
  1 +/**
  2 + * 内部路牌对象。
  3 + * @constructor
  4 + */
  5 +var InternalLpObj = function(
  6 + orilpObj, // 原始路牌对象
  7 + qCount, // 总共多少圈
  8 + isUp // 圈是以上行开始还是下行开始
  9 +) {
  10 + // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
  11 + this._$$_orign_lp_obj = orilpObj;
  12 +
  13 + this._$_isUp = isUp;
  14 +
  15 + // 路牌的圈数,注意每个路牌的圈数都是一致的,
  16 + // 但并不是每一圈都有值
  17 + // 第1圈从上标线开始
  18 + // 第0圈表示中标线的第一个班次组成的半圈
  19 + // 有多少圈根据最终迭代的结果来看
  20 + this._$_qCount = qCount;
  21 + // 保存的是 InternalGroupBcObj 对象
  22 + this._$_groupBcArray = new Array(qCount);
  23 +
  24 + var i;
  25 + for (i = 0; i < this._$_qCount; i++) {
  26 + this._$_groupBcArray[i] = new InternalGroupObj(
  27 + this, this._$_isUp, undefined, undefined);
  28 + }
  29 +
  30 + // 距离上一个路牌的最小发车间隔时间
  31 + // 用于纵向添加班次的时候使用
  32 + // 默认第一个路牌为0
  33 + this._$_minVerticalIntervalTime = 0;
  34 +
  35 + // 详细记录每圈每个方向上的发车间隔时间
  36 + // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
  37 + // 第一个方向是否上行由 _$_isUp 决定
  38 + // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
  39 + // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
  40 + this._$_aVerticalIntervalTime = new Array(this._$_qCount);
  41 + var i;
  42 + for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
  43 + this._$_aVerticalIntervalTime[i] = new Array(2);
  44 + }
  45 +
  46 + // 班型的相关变量
  47 + this._$_bx_isLb = false; // 是否连班
  48 + this._$_bx_isfb = false; // 是否分班
  49 + this._$_bx_isfb_5_2 = false; // 是否5休2分班
  50 + this._$_bx_desc; // 班型描述(默认为路牌编号)
  51 +
  52 + // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
  53 + this._$_other_bc_array = [];
  54 +
  55 + // TODO:
  56 +
  57 +};
  58 +
  59 +//------------------- get/set 方法 -------------------//
  60 +
  61 +InternalLpObj.prototype.getOtherBcArray = function() {
  62 + return this._$_other_bc_array;
  63 +};
  64 +InternalLpObj.prototype.addOtherBcArray = function(ba) {
  65 + this._$_other_bc_array = this._$_other_bc_array.concat(ba);
  66 +};
  67 +
  68 +/**
  69 + * 获取圈
  70 + * @param qIndex 圈index
  71 + */
  72 +InternalLpObj.prototype.getGroup = function(qIndex) {
  73 + return this._$_groupBcArray[qIndex];
  74 +};
  75 +
  76 +/**
  77 + * 获取班次。
  78 + * @param qIndex 第几圈
  79 + * @param bcIndex 第几个班次
  80 + */
  81 +InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
  82 + var group = this._$_groupBcArray[qIndex];
  83 + var bc;
  84 + if (bcIndex == 0) {
  85 + bc = group.getBc1();
  86 + } else if (bcIndex == 1) {
  87 + bc = group.getBc2();
  88 + }
  89 + return bc;
  90 +};
  91 +
  92 +/**
  93 + * 在具体位置设置班次。
  94 + * @param qIndex 第几圈
  95 + * @param bcIndex 第几个班次
  96 + * @param bc 班次对象
  97 + */
  98 +InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
  99 + var group = this._$_groupBcArray[qIndex];
  100 + if (bcIndex == 0) {
  101 + group.setBc1(bc);
  102 + bc.setGroup(group);
  103 + } else if (bcIndex == 1) {
  104 + group.setBc2(bc);
  105 + bc.setGroup(group);
  106 + }
  107 +};
  108 +
  109 +/**
  110 + * 设置原始路牌对象。
  111 + * @param lpObj 原始路牌对象
  112 + */
  113 +InternalLpObj.prototype.setLp = function(lpObj) {
  114 + this._$$_orign_lp_obj = lpObj;
  115 + var i;
  116 + var group;
  117 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  118 + group = this._$_groupBcArray[i];
  119 + if (group) {
  120 + group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
  121 + }
  122 + }
  123 +};
  124 +
  125 +InternalLpObj.prototype.getLpNo = function() {
  126 + return this._$$_orign_lp_obj.lpNo;
  127 +};
  128 +InternalLpObj.prototype.getLpName = function() {
  129 + return this._$$_orign_lp_obj.lpName;
  130 +};
  131 +InternalLpObj.prototype.setBxFb5_2 = function(fb) {
  132 + this._$_bx_isfb_5_2 = fb;
  133 +};
  134 +InternalLpObj.prototype.isBxFb5_2 = function() {
  135 + return this._$_bx_isfb_5_2;
  136 +};
  137 +InternalLpObj.prototype.setBxLb = function(lb) {
  138 + this._$_bx_isLb = lb;
  139 +};
  140 +InternalLpObj.prototype.isBxLb = function() {
  141 + return this._$_bx_isLb;
  142 +};
  143 +
  144 +InternalLpObj.prototype.setBxFb = function(fb) {
  145 + this._$_bx_isfb = fb;
  146 +};
  147 +InternalLpObj.prototype.isBxFb = function() {
  148 + return this._$_bx_isfb;
  149 +};
  150 +
  151 +/**
  152 + * 设置路牌的班型描述(最终是设置班次的路牌名字)。
  153 + * @param desc 描述
  154 + */
  155 +InternalLpObj.prototype.setBxDesc = function(desc) {
  156 + // 最终原始路牌的名字
  157 + this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
  158 + // 内部对象的班型描述
  159 + this._$_bx_desc = desc;
  160 +};
  161 +/**
  162 + * 获取版型描述
  163 + * @returns string
  164 + */
  165 +InternalLpObj.prototype.getBxDesc = function() {
  166 + return this._$_bx_desc;
  167 +};
  168 +
  169 +/**
  170 + * 设置纵向最小发车间隔时间。
  171 + * @param v
  172 + */
  173 +InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
  174 + // 第一个路牌,都为0
  175 + this._$_minVerticalIntervalTime = v;
  176 +};
  177 +/**
  178 + * 获取纵向最小发车间隔时间。
  179 + * @returns {number|*}
  180 + */
  181 +InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
  182 + return this._$_minVerticalIntervalTime;
  183 +};
  184 +
  185 +/**
  186 + * 设置纵向发车间隔。
  187 + * @param iQindex 圈index
  188 + * @param iBindex 班次index
  189 + * @param iTime 间隔时间
  190 + */
  191 +InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
  192 + this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
  193 +};
  194 +
  195 +/**
  196 + * 返回纵向发车间隔。
  197 + * @param iQindex 圈index
  198 + * @param iBindex 班次index
  199 + */
  200 +InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
  201 + return this._$_aVerticalIntervalTime[iQindex][iBindex];
  202 +};
  203 +
  204 +//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
  205 +
  206 +/**
  207 + * 返回总共班次数。
  208 + */
  209 +InternalLpObj.prototype.getBcCount = function() {
  210 + var i;
  211 + var group;
  212 + var bccount = 0;
  213 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  214 + group = this._$_groupBcArray[i];
  215 + if (group) {
  216 + if (group.getBc1()) {
  217 + bccount += 1;
  218 + }
  219 + if (group.getBc2()) {
  220 + bccount += 1;
  221 + }
  222 + }
  223 + }
  224 +
  225 + return bccount;
  226 +};
  227 +
  228 +/**
  229 + * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
  230 + * @returns arrays (InternalBcObj)
  231 + */
  232 +InternalLpObj.prototype.getBcArray = function() {
  233 + var bcArray = [];
  234 + var i;
  235 + var group;
  236 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  237 + group = this._$_groupBcArray[i];
  238 + if (group) {
  239 + group.getBc1() ? bcArray.push(group.getBc1()) : "";
  240 + group.getBc2() ? bcArray.push(group.getBc2()) : "";
  241 + }
  242 + }
  243 +
  244 + return bcArray;
  245 +};
  246 +
  247 +/**
  248 + * 获取最小(最早)班次对象。
  249 + * @returns [{圈index},{班次index}]
  250 + */
  251 +InternalLpObj.prototype.getMinBcObjPosition = function() {
  252 + var i;
  253 + var bIndex = [];
  254 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  255 + if (this._$_groupBcArray[i].getBc1()) {
  256 + bIndex.push(i);
  257 + bIndex.push(0);
  258 + break;
  259 + }
  260 + if (this._$_groupBcArray[i].getBc2()) {
  261 + bIndex.push(i);
  262 + bIndex.push(1);
  263 + break;
  264 + }
  265 + }
  266 + return bIndex;
  267 +};
  268 +
  269 +/**
  270 + * 获取最大(最晚)班次对象。
  271 + * @returns [{圈index},{班次index}]
  272 + */
  273 +InternalLpObj.prototype.getMaxBcObjPosition = function() {
  274 + var i;
  275 + var bIndex = [];
  276 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  277 + if (this._$_groupBcArray[i].getBc2()) {
  278 + bIndex.push(i);
  279 + bIndex.push(1);
  280 + break;
  281 + }
  282 + if (this._$_groupBcArray[i].getBc1()) {
  283 + bIndex.push(i);
  284 + bIndex.push(0);
  285 + break;
  286 + }
  287 + }
  288 + return bIndex;
  289 +};
  290 +
  291 +InternalLpObj.prototype.getMinBcObj = function() {
  292 + var i;
  293 + var bcObj;
  294 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  295 + bcObj = this._$_groupBcArray[i].getBc1();
  296 + if (bcObj) {
  297 + break;
  298 + }
  299 + bcObj = this._$_groupBcArray[i].getBc2();
  300 + if (bcObj) {
  301 + break;
  302 + }
  303 + }
  304 + return bcObj;
  305 +};
  306 +InternalLpObj.prototype.getMaxBcObj = function() {
  307 + var i;
  308 + var bcObj;
  309 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  310 + bcObj = this._$_groupBcArray[i].getBc2();
  311 + if (bcObj) {
  312 + break;
  313 + }
  314 + bcObj = this._$_groupBcArray[i].getBc1();
  315 + if (bcObj) {
  316 + break;
  317 + }
  318 + }
  319 + return bcObj;
  320 +};
  321 +
  322 +/**
  323 + * 获取车次链信息。
  324 + * @param num 第几个车次链
  325 + * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
  326 + */
  327 +InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
  328 + // 计算总的车次链信息
  329 + var aChainInfo = [];
  330 + var oChainInfo;
  331 + var aBcIndex = this.getMinBcObjPosition();
  332 + var oBc;
  333 + var iQIndex;
  334 + var iBcIndex;
  335 + var i;
  336 + var bFlag;
  337 +
  338 + var iBcount = 0;
  339 +
  340 + if (aBcIndex.length == 2) {
  341 + iBcount = 1;
  342 + oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
  343 + aChainInfo.push(oChainInfo);
  344 + bFlag = true;
  345 +
  346 + // 下一个班次的索引
  347 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  348 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  349 +
  350 + for (i = iQIndex; i < this._$_qCount; i++) {
  351 + while (iBcIndex <= 1) {
  352 + oBc = this.getBc(i, iBcIndex);
  353 + if (!oBc) {
  354 + if (bFlag) {
  355 + // 车次链结尾是这个班次的前一个班次
  356 + oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
  357 + oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
  358 + oChainInfo.bcount = iBcount;
  359 + }
  360 +
  361 + bFlag = false;
  362 + } else {
  363 + if (bFlag) {
  364 + iBcount ++;
  365 + oChainInfo.bcount = iBcount;
  366 + } else {
  367 + // 下一个车次链开始
  368 + iBcount = 1;
  369 + oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
  370 + aChainInfo.push(oChainInfo);
  371 + bFlag = true;
  372 + }
  373 + }
  374 +
  375 +
  376 + iBcIndex ++;
  377 + }
  378 + iBcIndex = 0;
  379 + }
  380 +
  381 + }
  382 +
  383 + return aChainInfo[num];
  384 +};
  385 +
  386 +/**
  387 + * 获取车次链的个数。
  388 + * @returns int
  389 + */
  390 +InternalLpObj.prototype.fnGetBcChainCount = function() {
  391 + var iChainCount = 0;
  392 + var aBcIndex = this.getMinBcObjPosition();
  393 +
  394 + var oBc;
  395 + var iQIndex;
  396 + var iBcIndex;
  397 + var i;
  398 + var bFlag;
  399 +
  400 + if (aBcIndex.length == 2) {
  401 + iChainCount = 1;
  402 + bFlag = true;
  403 +
  404 + // 下一个班次的索引
  405 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  406 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  407 +
  408 + for (i = iQIndex; i < this._$_qCount; i++) {
  409 + while (iBcIndex <= 1) {
  410 + oBc = this.getBc(i, iBcIndex);
  411 + if (!oBc) {
  412 + bFlag = false;
  413 + } else {
  414 + if (bFlag) {
  415 +
  416 + } else {
  417 + iChainCount ++;
  418 + bFlag = true;
  419 + }
  420 + }
  421 +
  422 +
  423 + iBcIndex ++;
  424 + }
  425 + iBcIndex = 0;
  426 + }
  427 +
  428 + }
  429 +
  430 +
  431 + return iChainCount;
  432 +};
  433 +
  434 +/**
  435 + * 在具体位置移除班次。
  436 + * @param qIndex 第几圈
  437 + * @param bcIndex 第几个班次
  438 + */
  439 +InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
  440 + var group = this._$_groupBcArray[qIndex];
  441 + if (bcIndex == 0) {
  442 + group.removeBc1();
  443 + } else if (bcIndex == 1) {
  444 + group.removeBc2();
  445 + }
  446 +};
  447 +
  448 +/**
  449 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  450 + * 使用时间差的绝度值,比较,取最小的
  451 + * 如果有两个一样的时间差,取比fctime大的时间
  452 + * @param fctime moment 比较用时间
  453 + * @param groupArray 圈数组
  454 + * @param hasUp boolean 计算上行班次
  455 + * @param hasDown boolean 计算下行班次
  456 + * @returns [{第几圈},{第几个班次}]
  457 + */
  458 +InternalLpObj.prototype.fnGetQBcIndexWithFcTimeFromGroupArray = function(
  459 + fctime, groupArray, hasUp, hasDown
  460 +) {
  461 + var i;
  462 + var timediff; // 时间差取绝对值
  463 + var qIndex;
  464 + var bcIndex;
  465 +
  466 + var group;
  467 + var bc1time;
  468 + var bc2time;
  469 +
  470 + var tempdiff;
  471 +
  472 + console.log("比较时间=" + fctime.format("HH:mm"));
  473 +
  474 + for (i = 0; i < this._$_qCount; i++) {
  475 + group = groupArray[i];
  476 + if (group) {
  477 + if (group.getBc1() && hasUp) {
  478 + bc1time = group.getBc1().getFcTimeObj();
  479 + console.log("bc1time=" + bc1time.format("HH:mm") + " tempdiff=" + tempdiff);
  480 + tempdiff = Math.abs(bc1time.diff(fctime));
  481 +
  482 + if (!timediff) {
  483 + timediff = Math.abs(tempdiff);
  484 + qIndex = i;
  485 + bcIndex = 0;
  486 + } else {
  487 + if (tempdiff < timediff) {
  488 + timediff = tempdiff;
  489 + qIndex = i;
  490 + bcIndex = 0;
  491 + } if (Math.abs(tempdiff) == timediff) {
  492 + if (bc1time.isAfter(fctime)) {
  493 + timediff = tempdiff;
  494 + qIndex = i;
  495 + bcIndex = 0;
  496 + }
  497 +
  498 + }
  499 + }
  500 + }
  501 +
  502 + if (group.getBc2() && hasDown) {
  503 + bc2time = group.getBc2().getFcTimeObj();
  504 + console.log("bc2time=" + bc2time.format("HH:mm") + " tempdiff=" + tempdiff);
  505 + tempdiff = Math.abs(bc2time.diff(fctime));
  506 +
  507 + if (!timediff) {
  508 + timediff = Math.abs(tempdiff);
  509 + qIndex = i;
  510 + bcIndex = 1;
  511 + } else {
  512 + if (tempdiff < timediff) {
  513 + timediff = tempdiff;
  514 + qIndex = i;
  515 + bcIndex = 1;
  516 + } if (Math.abs(tempdiff) == timediff) {
  517 + if (bc2time.isBefore(fctime)) {
  518 + timediff = tempdiff;
  519 + qIndex = i;
  520 + bcIndex = 1;
  521 + }
  522 +
  523 + }
  524 + }
  525 + }
  526 + }
  527 + }
  528 +
  529 + console.log("中标线对应数组索引=" + qIndex);
  530 +
  531 + var rst = [];
  532 + rst.push(qIndex);
  533 + rst.push(bcIndex);
  534 +
  535 + return rst;
  536 +};
  537 +
  538 +/**
  539 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  540 + * 使用时间差的绝度值,比较,取最小的
  541 + * 如果有两个一样的时间差,取比fctime大的时间
  542 + * @param fctime moment 比较用时间
  543 + * @param hasUp boolean 计算上行班次
  544 + * @param hasDown boolean 计算下行班次
  545 + * @returns [{第几圈},{第几个班次}]
  546 + */
  547 +InternalLpObj.prototype.getQBcIndexWithFcTime = function(
  548 + fctime, hasUp, hasDown
  549 +) {
  550 + return this.fnGetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
  551 +};
  552 +
  553 +//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
  554 +
  555 +/**
  556 + * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
  557 + * 注意,之前有班次会删除后再创建。
  558 + * @param startTime 开始时间
  559 + * @param endTime 结束时间
  560 + * @param isUp 第一个班次是上行还是下行
  561 + * @param fromQ 从第几圈开始加入
  562 + * @param paramObj 参数对象
  563 + * @param factory 工厂对象
  564 + */
  565 +InternalLpObj.prototype.initDataFromTimeToTime = function(
  566 + startTime,
  567 + endTime,
  568 + isUp,
  569 + fromQ,
  570 + paramObj,
  571 + factory) {
  572 +
  573 + var bcData = []; // 班次数组
  574 + var bcObj;
  575 + var kssj = startTime;
  576 + var fcno = 1; // 发车顺序号
  577 + var bcCount = 1; // 班次数
  578 + do {
  579 + bcObj = factory.createBcObj(
  580 + this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
  581 + bcData.push(bcObj);
  582 +
  583 + kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
  584 + fcno ++;
  585 + bcCount ++;
  586 + isUp = !isUp;
  587 + } while(kssj.isBefore(endTime));
  588 + bcCount--;
  589 +
  590 + //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
  591 + //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
  592 + //console.log("endtime: " + endTime.format("HH:mm"));
  593 +
  594 + //if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
  595 + // // 如果最后一个班次的到达时间超过结束时间,也要去除
  596 + // bcData.splice(bcCount - 1, 1);
  597 + //}
  598 +
  599 + this._initDataFromLbBcArray(bcData, fromQ);
  600 +
  601 +};
  602 +
  603 +/**
  604 + * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
  605 + * @param bcArray 连班班次数组
  606 + * @param fromQ 从第几圈开始加入
  607 + */
  608 +InternalLpObj.prototype._initDataFromLbBcArray = function(
  609 + bcArray,
  610 + fromQ
  611 +) {
  612 + var _bc1Obj;
  613 + var _bc2Obj;
  614 + var _qObj;
  615 +
  616 + // 第一班次是上行还是下行
  617 + var isUp = bcArray[0].isUp();
  618 +
  619 + if (bcArray.length > 0 && fromQ < this._$_qCount) {
  620 + // 构造圈数
  621 + if (isUp != this._$_isUp) {
  622 + // 如果方向不一致,意味着第一个班次是半圈
  623 + // 加半圈,并加在bc2上
  624 + _bc2Obj = bcArray.slice(0, 1)[0];
  625 + _qObj = new InternalGroupObj(
  626 + this,
  627 + this._$_isUp,
  628 + undefined,
  629 + _bc2Obj
  630 + );
  631 + _bc2Obj.setGroup(_qObj);
  632 + this._$_groupBcArray[fromQ] = _qObj;
  633 +
  634 + bcArray.splice(0, 1);
  635 + fromQ ++;
  636 + }
  637 +
  638 + var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
  639 + var qCount2 = bcArray.length % 2; // 最后是否有半圈
  640 +
  641 + while (fromQ < this._$_qCount) {
  642 + if (qCount1 > 0) {
  643 + _bc1Obj = bcArray.slice(0, 1)[0];
  644 + _bc2Obj = bcArray.slice(1, 2)[0];
  645 + _qObj = new InternalGroupObj(
  646 + this,
  647 + this._$_isUp,
  648 + _bc1Obj,
  649 + _bc2Obj
  650 + );
  651 + _bc1Obj.setGroup(_qObj);
  652 + _bc2Obj.setGroup(_qObj);
  653 + this._$_groupBcArray[fromQ] = _qObj;
  654 +
  655 + bcArray.splice(0, 2);
  656 + qCount1 --;
  657 + } else if (qCount2 > 0) {
  658 + // 加半圈,并加在bc1上
  659 + _bc1Obj = bcArray.slice(0, 1)[0];
  660 + _qObj = new InternalGroupObj(
  661 + this,
  662 + this._$_isUp,
  663 + _bc1Obj,
  664 + undefined
  665 + );
  666 + _bc1Obj.setGroup(_qObj);
  667 + this._$_groupBcArray[fromQ] = _qObj;
  668 +
  669 + bcArray.splice(0, 1);
  670 + qCount2 --;
  671 + } else {
  672 + break;
  673 + }
  674 +
  675 + fromQ ++;
  676 + }
  677 + }
  678 +};
  679 +
  680 +//-------------------------- 其他方法 ----------------------------//
  681 +
  682 +/**
  683 + * 从指定位置的班次开始,往后所有的班次修正发车时间
  684 + * @param groupIndex
  685 + * @param bcIndex
  686 + * @param time
  687 + */
  688 +InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
  689 + var i;
  690 + var oCurBc;
  691 +
  692 + // 修正之前班次的停站时间
  693 + //oCurBc = this.getBc(
  694 + // bcIndex == 0 ? groupIndex - 1 : groupIndex,
  695 + // bcIndex == 1 ? 0 : 1
  696 + //);
  697 + //if (oCurBc) {
  698 + // oCurBc.setStopTime(oCurBc.getStopTime() + time);
  699 + //}
  700 +
  701 +
  702 + for (i = groupIndex; i < this._$_qCount; i++) {
  703 + if (bcIndex == 0) {
  704 + oCurBc = this.getBc(i, 0);
  705 + if (oCurBc) {
  706 + oCurBc.addMinuteToFcsj(time);
  707 + }
  708 + oCurBc = this.getBc(i, 1);
  709 + if (oCurBc) {
  710 + oCurBc.addMinuteToFcsj(time);
  711 + }
  712 +
  713 + } else {
  714 + oCurBc = this.getBc(i, 1);
  715 + if (oCurBc) {
  716 + oCurBc.addMinuteToFcsj(time);
  717 + }
  718 +
  719 + }
  720 +
  721 + bcIndex = 0;
  722 + }
  723 +};
  724 +
  725 +/**
  726 + * 在指定位置添加一个吃饭班次。
  727 + * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
  728 + * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
  729 + * @param groupIndex
  730 + * @param bcIndex
  731 + * @param factory
  732 + * @param paramObj
  733 + * @returns int 相差时间(吃饭时间距离和停站时间相差值)
  734 + */
  735 +InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
  736 + var oPreBc;
  737 + var oEatBc;
  738 + var iBcModifyTime;
  739 + oPreBc = this.getBc( // 前一个邻接班次
  740 + bcIndex == 0 ? groupIndex - 1 : groupIndex,
  741 + bcIndex == 1 ? 0 : 1);
  742 + if (oPreBc) { // 存在前一个班次
  743 + oEatBc = factory.createBcObj(
  744 + this,
  745 + "cf",
  746 + !oPreBc.isUp(), // 和上一个班次方向相反
  747 + 1,
  748 + paramObj.addMinute(oPreBc.getArrTimeObj(), oPreBc.getStopTime()), // 使用上一个班次的到达时间作为开始时间
  749 + paramObj
  750 + );
  751 +
  752 + //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间
  753 +
  754 + // 修正之后的班次发车时间
  755 + // 注意:之后那个班次发车时间就是吃饭班次的到达时间
  756 + iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");
  757 + this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);
  758 +
  759 + oPreBc.setStopTime(0); // 不重置停站时间
  760 + oPreBc.fnSetEatTime(oEatBc.getBcTime());
  761 +
  762 + //this._$_other_bc_array.push(oEatBc);
  763 +
  764 + return iBcModifyTime;
  765 + } else {
  766 + return false;
  767 + }
  768 +
  769 +};
  770 +
  771 +/**
  772 + * 调整路牌的班次,通过调整停站时间,或者班次发车时间,不能让班次的到达时间和下一个班次的发车时间重叠。
  773 + * @param iPeakAverStopTime 高峰平均停站时间
  774 + * @param iTroughAverStopTime 低谷平均停站时间
  775 + * @param oParam 参数对象
  776 + */
  777 +InternalLpObj.prototype.fnAdjustBcInterval = function(iPeakAverStopTime, iTroughAverStopTime, oParam) {
  778 + // 获取车次链个数
  779 + var iBcChainCount = this.fnGetBcChainCount();
  780 +
  781 + var i;
  782 + var j;
  783 + var oBcIndex;
  784 + var iQIndex;
  785 + var iBcIndex;
  786 + var iBcCount;
  787 + var oBc;
  788 + var oNextBc;
  789 +
  790 + var iBcStopTime;
  791 +
  792 + for (i = 0; i < iBcChainCount; i++) {
  793 + oBcIndex = this.fnGetBcChainInfo(i);
  794 + iQIndex = oBcIndex["s_q"];
  795 + iBcIndex = oBcIndex["s_b"];
  796 + iBcCount = oBcIndex["bcount"];
  797 +
  798 + for (j = 0; j < iBcCount - 1; j++) {
  799 + oBc = this.getBc(iQIndex, iBcIndex);
  800 + oNextBc = this.getBc(
  801 + iBcIndex == 0 ? iQIndex : iQIndex + 1,
  802 + iBcIndex == 0 ? 1 : 0);
  803 +
  804 + if (oNextBc.fnIsFirstBc()) { // 如果同一路牌连续2个方向首站班次,都不做处理
  805 + continue;
  806 + }
  807 +
  808 + // 不改变当前班次的行驶时间,修正停站时间和下一个班次的发车时间
  809 + iBcStopTime = oNextBc.getFcTimeObj().diff(oBc.getArrTimeObj(), "m");
  810 + if (iBcStopTime < 0) {
  811 + // 当前班次使用最小停站时间
  812 + oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
  813 + oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
  814 +
  815 + } else {
  816 + if (iBcStopTime == oBc.getStopTime() + oBc.fnGetEatTime()) {
  817 + // 停站时间一致,没有问题
  818 +
  819 +
  820 + } else {
  821 + // TODO:当前班次使用最小停站时间
  822 + oBc.setStopTime(oParam.fnCalcuFixedMinStopNumber(oBc.getArrTimeObj(), oBc.isUp()));
  823 + oNextBc.addMinuteToFcsj(oBc.getStopTime() + oBc.fnGetEatTime() - iBcStopTime);
  824 +
  825 + }
  826 + }
  827 +
  828 + iBcIndex = iBcIndex == 0 ? 1 : 0;
  829 + iQIndex = iBcIndex == 0 ? iQIndex + 1 : iQIndex;
  830 + }
  831 +
  832 + this.getBc(iQIndex, iBcIndex).setStopTime(0);
  833 + }
  834 +
  835 +
  836 +};
  837 +
  838 +
  839 +// TODO
  840 +
  841 +/**
  842 + *
  843 + *
  844 + */
  845 +InternalLpObj.prototype.calcuLpBx = function() {
  846 +
  847 +};
  848 +
  849 +
  850 +
  851 +
  852 +
  853 +
  854 +
... ...
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalScheduleObj.js
1   -/**
2   - * 内部行车计划对象。
3   - * @constructor
4   - */
5   -var InternalScheduleObj = function(paramObj, lpArray, factory) {
6   - // 参数对象
7   - var _paramObj = paramObj;
8   - // 外部的路牌数组
9   - var _lpArray = lpArray;
10   - // 工厂对象
11   - var _factory = factory;
12   -
13   - //------------------ 初始化方法1,以及计算关联的内部变量 -----------------//
14   - var _qIsUp; // 每一圈是上行开始还是下行开始
15   - var _qCount = 0; // 总的圈数
16   - var _internalLpArray = []; // 内部对象数组
17   - var _aBxDesc = [ // 各种班型描述(班型名称,平均工时,平均需要的班次数,平均工时)
18   - {'sType':'六工一休', 'fHoursV':6.66, 'fBcCount': 0, 'fAverTime': 0},
19   - {'sType':'五工一休', 'fHoursV':6.85, 'fBcCount': 0, 'fAverTime': 0},
20   - {'sType':'四工一休', 'fHoursV':7.14, 'fBcCount': 0, 'fAverTime': 0},
21   - {'sType':'三工一休', 'fHoursV':7.61, 'fBcCount': 0, 'fAverTime': 0},
22   - {'sType':'二工一休', 'fHoursV':8.57, 'fBcCount': 0, 'fAverTime': 0},
23   - {'sType':'一工一休', 'fHoursV':11.42, 'fBcCount': 0, 'fAverTime': 0},
24   - {'sType':'五工二休', 'fHoursV':7.99, 'fBcCount': 0, 'fAverTime': 0},
25   - {'sType':'无工休', 'fHoursV':5.43, 'fBcCount': 0, 'fAverTime': 0}
26   - ];
27   -
28   - var _fnInitFun1 = function() { // 初始化方法1
29   - console.log("//---------------- 行车计划,初始化方法1 start ----------------//");
30   -
31   - //----------------------- 1、确定上标线的方向,圈的方向 -------------------//
32   -
33   - // 确定_qIsUp,哪个方向的首班车晚就用哪个
34   - _qIsUp = _paramObj.getUpFirstDTimeObj().isBefore(
35   - _paramObj.getDownFirstDTimeObj()) ? false : true;
36   - // 上标线开始时间,就是方向的首班车时间
37   - var st = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
38   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
39   - var et;
40   - var et_IsUp;
41   - if (_paramObj.getUpLastDtimeObj().isBefore(
42   - _paramObj.getDownLastDTimeObj())) {
43   - et = _paramObj.getDownLastDTimeObj();
44   - et_IsUp = false;
45   - } else {
46   - et = _paramObj.getUpLastDtimeObj();
47   - et_IsUp = true;
48   - }
49   -
50   - //------------------------ 2、计算总共有多少圈 ------------------------//
51   -
52   - // 以开始时间,结束时间,构造上标线用连班班次发车时间
53   - var bcFcsjArrays = []; // 班次发车时间对象数组
54   - var bcArsjArrays = []; // 班次到达时间对象数组
55   - var isUp = _qIsUp; // 方向
56   - var bcCount = 1; // 班次数
57   -
58   - var _kssj = st; // 开始时间
59   - var _bcsj = paramObj.calcuTravelTime(_kssj, isUp); // 班次历时
60   - var _arrsj = paramObj.addMinute(_kssj, _bcsj); // 到达时间
61   - var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj); // 停站时间
62   -
63   - do {
64   - bcFcsjArrays.push(_kssj);
65   - bcArsjArrays.push(_arrsj);
66   -
67   - _kssj = paramObj.addMinute(_kssj, _bcsj + _stoptime);
68   - _bcsj = paramObj.calcuTravelTime(_kssj, isUp);
69   - _arrsj = paramObj.addMinute(_kssj, _bcsj);
70   - _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
71   -
72   - bcCount ++;
73   - isUp = !isUp;
74   - } while(_kssj.isBefore(et));
75   - bcCount--; // 因为先做do,所以总的班次要减1
76   - //if (bcCount > 0 && bcArsjArrays[bcCount - 1].isAfter(et)) {
77   - // // 如果最后一个班次的到达时间超过结束时间,也要去除
78   - // bcFcsjArrays.splice(bcCount - 1, 1);
79   - // bcArsjArrays.splice(bcCount - 1, 1);
80   - // bcCount--;
81   - //}
82   - var _qCount_p1 = Math.floor(bcCount / 2); // 2个班次一圈
83   - var _qCount_p2 = bcCount % 2; // 余下的1个班次也算一圈
84   -
85   - // 利用连班数组计算圈数
86   - _qCount = 1; // 前面加1圈,补中标线的班次
87   - _qCount += _qCount_p1;
88   - _qCount += _qCount_p2;
89   -
90   - // 计算最后是不是还要补一圈
91   - if (_qCount > 1) { // 总的圈数就1圈,没必要加了(其实是不可能的,除非参数里问题)
92   - if (_qCount_p2 == 0) { // 没有余下班次,整数圈数
93   - // 最后一个班次的方向一定和开始的方向相反,如:上-下,上-下,上-下,一共三圈,最后一个班次为下行
94   - // 判定最后一个班次的方向和上标线判定结束时间的班次方向是否一致
95   - if (!_qIsUp == et_IsUp) {
96   - // 一致不用加圈数
97   - } else {
98   - // 不一致需要加圈补最后一个结束时间班次
99   - _qCount ++;
100   - }
101   - } else {
102   - // 有余下的圈数,最后要不补的班次不管上行,下行都在这一圈里
103   - // 不需要在补圈数了
104   - }
105   - }
106   -
107   - //------------------------ 3、根据路牌数,圈数创建路牌对象 ----------------------//
108   -
109   - // 创建内部的路牌数组,并把之前的连班路牌添加进上标线路牌中
110   - var i;
111   - for (i = 0; i < _lpArray.length; i++) {
112   - _internalLpArray.push(new InternalLpObj(_lpArray[i], _qCount, _qIsUp));
113   - }
114   - // 初始化上标线,从第1圈开始
115   - _internalLpArray[0].initDataFromTimeToTime(bcFcsjArrays[0], et, _qIsUp, 1, _paramObj, _factory);
116   -
117   - // 以上标线为基础,计算各种班型工时对应的圈数、班次数
118   - var aBcArray = _internalLpArray[0].getBcArray();
119   - if (aBcArray.length % 2 != 0) { // 不能整除2,去除一个班次计算
120   - aBcArray.splice(aBcArray.length - 1, 1);
121   - }
122   -
123   - // 午饭吃饭时间
124   - var iLTime = _paramObj.fnGetLunchTime();
125   - // 晚饭吃饭时间
126   - var iDTime = _paramObj.fnGetDinnerTime();
127   - // 出场时间
128   - var iOutTime = _qIsUp ? _paramObj.getUpOutTime() : _paramObj.getDownOutTime();
129   - // 进场时间
130   - var iInTime = _qIsUp ? _paramObj.getDownInTime() : _paramObj.getUpInTime();
131   - // 例保时间
132   - var iBTime = _paramObj.getLbTime();
133   -
134   - var sum = 0; // 总班次时间
135   - for (i = 0; i < aBcArray.length; i++) {
136   - sum += aBcArray[i].getBcTime() + aBcArray[i].getStopTime();
137   - }
138   - sum += iLTime; // 加午饭时间
139   - sum += iDTime; // 加晚饭时间
140   - for (i = 0; i < _aBxDesc.length; i++) {
141   - _aBxDesc[i].fAverTime = sum / (aBcArray.length / 2); // 平均周转时间不算进出场,例保时间
142   -
143   - // 计算5休2的班次数(双进出场,4个例保)
144   - if (i == 6) {
145   - _aBxDesc[i].fQCount =
146   - (_aBxDesc[i].fHoursV * 60 - iOutTime * 2 - iInTime * 2 - iBTime * 4) /
147   - _aBxDesc[i].fAverTime;
148   - _aBxDesc[i].fBcCount = _aBxDesc[i].fQCount * 2;
149   - } else { // 进出场,2个例保
150   - _aBxDesc[i].fQCount =
151   - (_aBxDesc[i].fHoursV * 60 - iOutTime - iInTime - iBTime * 2) /
152   - _aBxDesc[i].fAverTime;
153   - _aBxDesc[i].fBcCount = _aBxDesc[i].fQCount * 2;
154   - }
155   - }
156   -
157   -
158   - // 在第一个班次之前再添加一个模拟班次,用于中标线的作用
159   - // 那一圈必定是低谷,而且圈索引0,班次索引1,暂时标记,最后删除
160   - var iFirstStopTime =
161   - _paramObj.fnCalcuFixedStopNumber(
162   - _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -10),
163   - _qIsUp
164   - );
165   - var iXXTime = _qIsUp ? _paramObj.getDownTroughTime() : _paramObj.getUpTroughTime();
166   - var oFlagBc = _factory.createBcObj( // 标记班次
167   - _internalLpArray[0],
168   - "normal",
169   - !_qIsUp,
170   - 1,
171   - _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -(iFirstStopTime + iXXTime)),
172   - _paramObj
173   - );
174   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
175   -
176   - _internalLpArray[0].setBc(0, 1, oFlagBc);
177   -
178   - // 在最后一圈也补上一个或者2个模拟班次,暂时标记,最后需要删除
179   - var aMaxBcIndex = _internalLpArray[0].getMaxBcObjPosition();
180   - if (aMaxBcIndex[0] == _qCount - 1) { // 可能加半圈
181   - oFlagBc = _factory.createBcObj( // 标记班次
182   - _internalLpArray[0],
183   - "normal",
184   - !_qIsUp,
185   - 1,
186   - _paramObj.addMinute(
187   - _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
188   - _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
189   - _paramObj
190   - );
191   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
192   - _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
193   -
194   - } else { // 加完整的一圈
195   - oFlagBc = _factory.createBcObj( // 标记班次
196   - _internalLpArray[0],
197   - "normal",
198   - _qIsUp,
199   - 1,
200   - _paramObj.addMinute(
201   - _internalLpArray[0].getBc(_qCount - 2, 1).getArrTimeObj(),
202   - _internalLpArray[0].getBc(_qCount - 2, 1).getStopTime()),
203   - _paramObj
204   - );
205   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
206   - _internalLpArray[0].setBc(_qCount - 1, 0, oFlagBc);
207   -
208   - oFlagBc = _factory.createBcObj( // 标记班次
209   - _internalLpArray[0],
210   - "normal",
211   - !_qIsUp,
212   - 1,
213   - _paramObj.addMinute(
214   - _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
215   - _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
216   - _paramObj
217   - );
218   - oFlagBc.fnSetDelFlag(true); // 标记了删除记号
219   - _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
220   -
221   - }
222   -
223   - console.log("上行首班车时间:" + _paramObj.getUpFirstDTimeObj().format("HH:mm") +
224   - "上行末班车时间:" + _paramObj.getUpLastDtimeObj().format("HH:mm"));
225   - console.log("下行首班车时间:" + _paramObj.getDownFirstDTimeObj().format("HH:mm") +
226   - "下行末班车时间:" + _paramObj.getDownLastDTimeObj().format("HH:mm"));
227   - console.log("总共计算的圈数:" + _qCount);
228   - console.log("圈的方向isUP:" + _qIsUp);
229   - console.log("班型描述(以下):");
230   - console.log(_aBxDesc);
231   - console.log("所有路牌间隔描述(以下):");
232   - for (i = 0; i < _internalLpArray.length; i++) {
233   - console.log(_internalLpArray[i]._$_aVerticalIntervalTime);
234   - }
235   - console.log("//---------------- 行车计划,初始化方法1 end ----------------//");
236   -
237   - };
238   -
239   - //------------------ 初始化方法2,以及计算关联的内部变量 ----------------//
240   - var _approximate_zgfQIndex; // 预估早高峰车辆从第几圈开始全部发出
241   - var _approximate_zgfBIndex; // 预估早高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
242   - var _approximate_wgfQIndex; // 预估晚高峰车辆从第几圈开始全部发出
243   - var _approximate_wgfBIndex; // 预估晚高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
244   -
245   - var _fnInitFun2 = function() { // 初始化方法2
246   - console.log("//---------------- 行车计划,初始化方法2 start ----------------//");
247   -
248   - //------------------------ 1、计算车辆总数 ------------------------//
249   - // 是用高峰上行周转时间除以高峰平均间隔得到的
250   - // 这样算还算合理,车辆不多不少,待以后有新的算法再修正
251   - var iClCount = _paramObj.calcuClzx();
252   -
253   - //------------------------ 2、计算所有路牌的发车在各个圈中的间隔 --------------------//
254   - var i;
255   - var j;
256   - var iBindex = 1;
257   - var iZzsj;
258   - var oLp;
259   - var iC1;
260   - var iC2;
261   -
262   - for (i = 0; i < _qCount - 1; i++) {
263   - while (iBindex <= 1) {
264   - // 每圈每个方向的周转时间不一致,以上标线为主
265   - oLp = _internalLpArray[0];
266   - iZzsj = oLp.getBc(i + 1, iBindex).getFcTimeObj().diff(
267   - oLp.getBc(i, iBindex).getFcTimeObj(), "m"
268   - );
269   -
270   - iC1 = Math.floor(iZzsj / iClCount);
271   - iC2 = iZzsj % iClCount;
272   -
273   - for (j = 0; j < iClCount - iC2; j++) {
274   - oLp = _internalLpArray[j];
275   - oLp.fnSetVerticalIntervalTime(i, iBindex, iC1);
276   - }
277   -
278   - for (j = 0; j < iC2; j++) {
279   - oLp = _internalLpArray[iClCount - iC2 + j];
280   - oLp.fnSetVerticalIntervalTime(i, iBindex, iC1 + 1);
281   - }
282   -
283   - iBindex ++;
284   -
285   - }
286   - iBindex = 0;
287   - }
288   - // 最后一圈没有下一圈的参照,周转时间没发获取,由于都是低谷,所以使用倒数第二圈的间隔最为最后一圈的间隔
289   - for (i = 0; i < _internalLpArray.length; i++) {
290   - oLp = _internalLpArray[i];
291   - oLp.fnSetVerticalIntervalTime(_qCount - 1, 0, oLp.fnGetVerticalIntervalTime(_qCount - 2, 0));
292   - oLp.fnSetVerticalIntervalTime(_qCount - 1, 1, oLp.fnGetVerticalIntervalTime(_qCount - 2, 1));
293   - }
294   -
295   - //------------------------ 3、预估早高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
296   -
297   - // 以上标线为标准,查找离早高峰开始时间最近的班次作为早高峰开始班次
298   - // 以这个班次为早高峰起点,全部出车策略
299   - var qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
300   - _paramObj.getMPeakStartTimeObj(), true, true);
301   - var qIndex = qbcIndexArray[0]; // 第几圈
302   - var bIndex = qbcIndexArray[1]; // 第几个班次
303   -
304   - for (i = 1; i < _internalLpArray.length; i++) {
305   - _fnGenerateBcAndSetBc(i, qIndex, bIndex);
306   - }
307   -
308   - _approximate_zgfQIndex = qIndex;
309   - _approximate_zgfBIndex = bIndex;
310   -
311   - //------------------------ 4、预估晚高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
312   -
313   - // 以上标线为标准,查找离晚高峰开始时间最近的班次作为晚高峰开始班次
314   - // 以这个班次为早高峰起点,全部出车策略
315   - qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
316   - _paramObj.getEPeakStartTimeObj(), true, true);
317   - qIndex = qbcIndexArray[0]; // 第几圈
318   - bIndex = qbcIndexArray[1]; // 第几个班次
319   -
320   - for (i = 1; i < _internalLpArray.length; i++) {
321   - _fnGenerateBcAndSetBc(i, qIndex, bIndex);
322   - }
323   -
324   - _approximate_wgfQIndex = qIndex;
325   - _approximate_wgfBIndex = bIndex;
326   -
327   - console.log("早高峰周转时间(固定最大停战时间):" + _paramObj.calcuPeakZzsj() + "分钟");
328   - console.log("早高峰发车时间范围:" + _paramObj.getMPeakMinFcjx() + "分钟 --- " + _paramObj.getMPeakMaxFcjx() + "分钟");
329   - console.log("预估早高峰第" + _approximate_zgfQIndex + "(index)圈,第" + _approximate_zgfBIndex + "(index)班次车辆全部发出");
330   - console.log("预估晚高峰第" + _approximate_wgfQIndex + "(index)圈,第" + _approximate_wgfBIndex + "(index)班次车辆全部发出");
331   - console.log("//---------------- 行车计划,初始化方法2 end ----------------//");
332   - };
333   -
334   - //----------------------- 初始化方法3,计算连班分班的路牌分布 ----------------//
335   - var _iBx_lb_lpcount; // 连班路牌数
336   - var _iBx_5_2_fb_lpcount; // 5休2分班路牌数
337   - var _iBx_other_fb_lpcount; // 其他分班路牌数
338   -
339   - var _fnInitFun3 = function() { // 初始化方法3
340   - console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
341   -
342   - //--------------------- 1、计算分班连班班型车辆分布数 --------------------//
343   - // 总共车辆数(高峰最大车辆数)
344   - var iCls = _paramObj.calcuClzx();
345   - // 低谷最少配车(连班车数量)
346   - var iDgminpc = Math.round(_paramObj.calcuTroughZzsj() / _paramObj.getTroughMaxFcjx());
347   - // 加班车路牌数(做5休2的路牌数)
348   - var i_5_2_lpes = _paramObj.getJBLpes();
349   -
350   - // 做些简单的验证
351   - if (iCls < iDgminpc) {
352   - alert("总配车数小于低谷最小配车");
353   - throw "总配车数小于低谷最小配车";
354   - }
355   - if (iDgminpc < 2) {
356   - alert("连班路牌小于2,办不到啊");
357   - throw "连班路牌小于2,办不到啊";
358   - }
359   - if (iCls - iDgminpc < i_5_2_lpes) {
360   - alert("总分班路牌数小于加班路牌数");
361   - throw "总分班路牌数小于加班路牌数";
362   - }
363   -
364   - //// 修正连班路牌数,班次间隔大于20的,加1,直至班次间隔小于20
365   - //while(_paramObj.calcuPeakZzsj() / iDgminpc > 20) {
366   - // iDgminpc ++;
367   - //}
368   - _iBx_lb_lpcount = iDgminpc;
369   -
370   - _iBx_5_2_fb_lpcount = i_5_2_lpes;
371   - _iBx_other_fb_lpcount = iCls - _iBx_lb_lpcount - i_5_2_lpes;
372   -
373   - //------------------------ 2、利用间隔法计算连班路牌分布 --------------------//
374   - var i;
375   - var j;
376   - var iC1 = Math.floor(_internalLpArray.length / _iBx_lb_lpcount);
377   - var iC2 = _internalLpArray.length % _iBx_lb_lpcount;
378   - var iLpIndex;
379   -
380   - for (i = 0; i < _iBx_lb_lpcount - iC2; i++) {
381   - iLpIndex = i * iC1;
382   - _internalLpArray[iLpIndex].setBxLb(true);
383   - _internalLpArray[iLpIndex].setBxDesc("连班");
384   - }
385   - for (j = 0; j < iC2; j++) {
386   - iLpIndex = i * iC1 + j * (iC1 + 1);
387   - _internalLpArray[iLpIndex].setBxLb(true);
388   - _internalLpArray[iLpIndex].setBxDesc("连班");
389   - }
390   -
391   - //------------------------ 3、利用间隔法计算分班班型路牌分布 --------------------//
392   - // 获取分班路牌索引
393   - var aNotLbIndexes = [];
394   - for (i = 0; i < _internalLpArray.length; i++) {
395   - if (!_internalLpArray[i].isBxLb()) {
396   - aNotLbIndexes.push(i);
397   - }
398   - }
399   - // 先5休2分班
400   - iC1 = Math.floor(aNotLbIndexes.length / _iBx_5_2_fb_lpcount);
401   - iC2 = aNotLbIndexes.length % _iBx_5_2_fb_lpcount;
402   -
403   - for (i = 0; i < _iBx_5_2_fb_lpcount - iC2; i++) {
404   - iLpIndex = aNotLbIndexes[i * iC1];
405   - _internalLpArray[iLpIndex].setBxLb(false);
406   - _internalLpArray[iLpIndex].setBxFb(true);
407   - _internalLpArray[iLpIndex].setBxFb5_2(true);
408   - _internalLpArray[iLpIndex].setBxDesc("5休2分班");
409   - }
410   - for (i = 0; i < iC2; i++) {
411   - iLpIndex = aNotLbIndexes[_iBx_5_2_fb_lpcount - iC2 + i * (iC1 + 1)];
412   - _internalLpArray[iLpIndex].setBxLb(false);
413   - _internalLpArray[iLpIndex].setBxFb(true);
414   - _internalLpArray[iLpIndex].setBxFb5_2(true);
415   - _internalLpArray[iLpIndex].setBxDesc("5休2分班");
416   - }
417   - // 其他分班
418   - for (i = 0; i < aNotLbIndexes.length; i++) {
419   - iLpIndex = aNotLbIndexes[i];
420   - if (!_internalLpArray[iLpIndex].isBxFb5_2()) {
421   - _internalLpArray[iLpIndex].setBxLb(false);
422   - _internalLpArray[iLpIndex].setBxFb(true);
423   - _internalLpArray[iLpIndex].setBxFb5_2(false);
424   - _internalLpArray[iLpIndex].setBxDesc("其他分班");
425   - }
426   - }
427   -
428   - console.log("高峰周转时间:" + _paramObj.calcuPeakZzsj());
429   - console.log("连班路牌数:" + _iBx_lb_lpcount);
430   - console.log("5休2分班路牌数:" + _iBx_5_2_fb_lpcount);
431   - console.log("其他分班路牌数:" + _iBx_other_fb_lpcount);
432   - var aLbIndexes = [];
433   - for (i = 0; i < _internalLpArray.length; i++) {
434   - if (_internalLpArray[i].isBxLb()) {
435   - aLbIndexes.push(i);
436   - }
437   - }
438   - console.log("连班路牌indexes=" + aLbIndexes);
439   - var a_5_2_fbIndexes = [];
440   - for (i = 0; i < _internalLpArray.length; i++) {
441   - if (_internalLpArray[i].isBxFb() && _internalLpArray[i].isBxFb5_2()) {
442   - a_5_2_fbIndexes.push(i);
443   - }
444   - }
445   - console.log("5休2分班路牌indexes=" + a_5_2_fbIndexes);
446   - var a_other_fbIndexes = [];
447   - for (i = 0; i < _internalLpArray.length; i++) {
448   - if (_internalLpArray[i].isBxFb() && !_internalLpArray[i].isBxFb5_2()) {
449   - a_other_fbIndexes.push(i);
450   - }
451   - }
452   - console.log("其他分班路牌indexes=" + a_other_fbIndexes);
453   -
454   - console.log("//---------------- 行车计划,初始化方法3 end ----------------//");
455   - };
456   -
457   - //----------------------- 初始化方法4,计算中标线位置 -------------------------//
458   - var _iZbx_lpIndex; // 中标线对应第几个路牌
459   -
460   - var _fnInitFun4 = function() { // 初始化方法4
461   - console.log("//---------------- 行车计划,初始化方法4 start ----------------//");
462   -
463   - //---------------------------- 1、模拟一个中标线,使用临时路牌 ----------------------//
464   - // 构造中标线
465   - // 中标线开始时间,就是方向的首班车时间
466   - var oSt = !_qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
467   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
468   - // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
469   - var oEt;
470   - if (_paramObj.getUpLastDtimeObj().isBefore(
471   - _paramObj.getDownLastDTimeObj())) {
472   - oEt = _paramObj.getDownLastDTimeObj();
473   - } else {
474   - oEt = _paramObj.getUpLastDtimeObj();
475   - }
476   -
477   - var oTempLp = new InternalLpObj({lpNo: -999, lpName: "-999"}, _qCount, _qIsUp);
478   - oTempLp.initDataFromTimeToTime(
479   - oSt,
480   - oEt,
481   - !_qIsUp,
482   - 0,
483   - _paramObj,
484   - _factory
485   - );
486   -
487   - //------------------------ 2、找出中标线的早高峰班次,计算应该插在当前路牌数组的那个位置 ----------------//
488   - // 找出中标线对应的早高峰的班次对象
489   - var oZb_gf_bc = oTempLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
490   -
491   - // 把所有连班路牌高峰班次重新构造成一个一个的圈数组,计算对应中标线最近的是第几个路牌
492   - // 中标线和上标线一样在连班路牌上
493   - var aTempq = [];
494   - var oTempq;
495   - var oTempb;
496   - var i;
497   - var oLp;
498   -
499   - var aLbIndexes = []; // 连班的路牌索引
500   - for (i = 0; i < _internalLpArray.length; i++) {
501   - if (_internalLpArray[i].isBxLb()) {
502   - aLbIndexes.push(i);
503   - }
504   - }
505   -
506   - for (i = 0; i < aLbIndexes.length; i++) {
507   - oLp = _internalLpArray[aLbIndexes[i]];
508   -
509   - oTempb = oLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
510   - if (oTempb.isUp() == _qIsUp) {
511   - oTempq = new InternalGroupObj(oLp, _qIsUp, oTempb, undefined);
512   - } else {
513   - oTempq = new InternalGroupObj(oLp, _qIsUp, undefined, oTempb);
514   - }
515   - aTempq.push(oTempq);
516   -
517   - }
518   -
519   - var aTtindex = oTempLp.getgetQBcIndexWithFcTimeFromGroupArray(
520   - oZb_gf_bc.getFcTimeObj(),
521   - aTempq,
522   - true,
523   - true
524   - );
525   -
526   - // 注意:如果中标线和上标线同一个路牌,需要把中标线移到下一个路牌
527   - if (aTtindex[0] == 0) { // 0是上标线路牌索引
528   - aTtindex[0] = aLbIndexes[1]; // 选择下一个连班路牌索引
529   - }
530   -
531   - _iZbx_lpIndex = aTtindex[0]; // 中标线放在第几个路牌
532   - oTempLp.setLp(_lpArray[_iZbx_lpIndex]); // 设置原始路牌对象
533   - oTempLp._$_aVerticalIntervalTime = _internalLpArray[_iZbx_lpIndex]._$_aVerticalIntervalTime; // 设置纵向最小发车间隔
534   - oTempLp.setBxLb(_internalLpArray[_iZbx_lpIndex].isBxLb());
535   - oTempLp.setBxFb(_internalLpArray[_iZbx_lpIndex].isBxFb());
536   - oTempLp.setBxFb5_2(_internalLpArray[_iZbx_lpIndex].isBxFb5_2());
537   -
538   - // 修正除了第一个班次外,其余其他班次
539   - var iBcindex = 0;
540   - for (i = 1; i < _qCount; i++) {
541   - while (iBcindex <= 1) {
542   - if (oTempLp.getBc(i, iBcindex)) { // 替换存在的班次
543   - oTempLp.setBc(i, iBcindex, _fnGenerateBc(_iZbx_lpIndex, i, iBcindex));
544   - }
545   - iBcindex ++;
546   - }
547   - iBcindex = 0;
548   - }
549   -
550   - _internalLpArray[_iZbx_lpIndex] = oTempLp;
551   -
552   - console.log("中标线对应第" + (_iZbx_lpIndex + 1) + "个路牌");
553   -
554   - console.log("//---------------- 行车计划,初始化方法4 end ----------------//");
555   - };
556   -
557   - //-------------------- 重要的内部方法 -----------------------//
558   - /**
559   - * 核心方法,利用路牌间隔纵向生成班次。
560   - * @param iLpindex 路牌索引
561   - * @param iQindex 圈索引
562   - * @param iBcindex 班次索引
563   - * @returns object InternalBcObj,失败 false
564   - */
565   - var _fnGenerateBc = function(iLpindex, iQindex, iBcindex) {
566   - // 以上标线为起始点,使用路牌在不同圈,班次索引的发车间隔,计算班次
567   - // 注意,发车间隔是指下一个班次应该距离当前班次间隔,是从下往上的
568   -
569   - // 1、参数验证
570   - if (iLpindex == 0) { // 上标线的班次不需要生成
571   - return false;
572   - }
573   -
574   - // 2、计算间隔
575   - var i;
576   - var oLp;
577   - var iTime = 0;
578   - for (i = 0; i < iLpindex; i++) {
579   - oLp = _internalLpArray[i];
580   - iTime += oLp.fnGetVerticalIntervalTime(iQindex, iBcindex);
581   - }
582   -
583   - // 3、生成班次
584   - var _oKsbc = _internalLpArray[0].getBc(iQindex, iBcindex);
585   - if (!_oKsbc) {
586   - return false;
587   - }
588   - var _oKssj = _paramObj.addMinute(_oKsbc.getFcTimeObj(), iTime);
589   - var _oBc = _factory.createBcObj(
590   - _internalLpArray[iLpindex],
591   - "normal", _oKsbc.isUp(),
592   - 1, _oKssj, _paramObj);
593   -
594   - return _oBc;
595   -
596   - };
597   -
598   - /**
599   - * 核心方法,在指定位置生成班次并添加到路牌指定位置中。
600   - * @param lpIndex 第几个路牌
601   - * @param qIndex 第几圈
602   - * @param bcIndex 第几个班次
603   - */
604   - var _fnGenerateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
605   - var _bcObj = _fnGenerateBc(lpIndex, qIndex, bcIndex);
606   - if (_bcObj) {
607   - _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
608   - }
609   - };
610   -
611   - /**
612   - * 获取班次列表。
613   - * @param oIsUp 是否上行
614   - * @param oStartTime 开始时间对象
615   - * @returns [(InternalBcObj)]
616   - */
617   - var _fnGetBcList2 = function(oIsUp, oStartTime) {
618   - var i;
619   - var j;
620   - var oLp;
621   - var oBc;
622   - var aBc = [];
623   -
624   - for (j = 0; j < _qCount; j++) {
625   - for (i = 0; i < _internalLpArray.length; i++) {
626   - oLp = _internalLpArray[i];
627   - oBc = oLp.getBc(
628   - j,
629   - _qIsUp == oIsUp ? 0 : 1
630   - );
631   - if (oBc && oBc.getFcTimeObj().isAfter(oStartTime)) {
632   - aBc.push(oBc);
633   - }
634   - }
635   - }
636   -
637   - var aBcFcTime = [];
638   - for (i = 0; i < aBc.length; i++) {
639   - oBc = aBc[i];
640   - aBcFcTime.push(oBc.getFcTimeObj().format("HH:mm"));
641   - }
642   - console.log((oIsUp ? "上行班次列表:" : "下行班次列表:") + aBcFcTime.join(","));
643   -
644   - return aBc;
645   - };
646   -
647   - /**
648   - * 获取班次列表。
649   - * @param isUp boolean 是否上行
650   - * @returns [(InternalBcObj)]
651   - */
652   - var _fnGetBcList = function(isUp) {
653   - var i;
654   - var j;
655   - var oLp;
656   - var oBc;
657   - var aBc = [];
658   -
659   - for (j = 0; j < _qCount; j++) {
660   - for (i = 0; i < _internalLpArray.length; i++) {
661   - oLp = _internalLpArray[i];
662   - oBc = oLp.getBc(
663   - j,
664   - _qIsUp == isUp ? 0 : 1
665   - );
666   - if (oBc) {
667   - aBc.push(oBc);
668   - }
669   - }
670   - }
671   -
672   - var aBcFcTime = [];
673   - for (i = 0; i < aBc.length; i++) {
674   - oBc = aBc[i];
675   - aBcFcTime.push(oBc.getFcTimeObj().format("HH:mm"));
676   - }
677   - console.log((isUp ? "上行班次列表:" : "下行班次列表:") + aBcFcTime.join(","));
678   -
679   - return aBc;
680   - };
681   -
682   - /**
683   - * 查找离指定时间最近的前面的班次索引信息
684   - * @param timeObj 查找时间
685   - * @param isUp 是否上行
686   - * @returns [{路牌index},{圈index},{班次index}]
687   - */
688   - var _fnFindUpClosedBcIndexWithTime = function(timeObj, isUp) {
689   -
690   - var _lpObj;
691   - var _groupObj;
692   - var _bcObj;
693   - var _i;
694   - var _j;
695   - var timediff; // 时间差取绝对值
696   -
697   - var _lpIndex;
698   - var _up_qIndex;
699   - var _up_bIndex;
700   -
701   - for (_i = 0; _i < _qCount; _i++) {
702   - for (_j = 0; _j < _internalLpArray.length; _j++) {
703   - _lpObj = _internalLpArray[_j];
704   - _groupObj = _lpObj.getGroup(_i);
705   - _bcObj = isUp == _qIsUp ? _groupObj.getBc1() : _groupObj.getBc2();
706   - if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
707   - _bcObj = _fnGenerateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
708   - }
709   - if (_bcObj) {
710   - if (timeObj.diff(_bcObj.getFcTimeObj()) >= 0) {
711   - if (!timediff) {
712   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
713   - _lpIndex = _j;
714   - _up_qIndex = _i;
715   - _up_bIndex = isUp == _qIsUp ? 0 : 1;
716   - } else {
717   - if (timeObj.diff(_bcObj.getFcTimeObj()) < timediff) {
718   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
719   - _lpIndex = _j;
720   - _up_qIndex = _i;
721   - _up_bIndex = isUp == _qIsUp ? 0 : 1;
722   - }
723   - }
724   - }
725   - }
726   - }
727   - }
728   -
729   - if (_lpIndex == undefined) {
730   - return false;
731   - }
732   -
733   - var bcindex = [];
734   - bcindex.push(_lpIndex);
735   - bcindex.push(_up_qIndex);
736   - bcindex.push(_up_bIndex);
737   -
738   - return bcindex;
739   - };
740   -
741   - /**
742   - * 查找离指定时间最近的后面的班次索引信息
743   - * @param timeObj 查找时间
744   - * @param isUp 是否上行
745   - * @returns [{路牌index},{圈index},{班次index}]
746   - */
747   - var _fnFindDownClosedBcIndexWithTime = function(timeObj, isUp) {
748   - var _lpObj;
749   - var _groupObj;
750   - var _bcObj;
751   - var _i;
752   - var _j;
753   - var timediff; // 时间差取绝对值
754   -
755   - var _lpIndex;
756   - var _down_qIndex;
757   - var _down_bIndex;
758   -
759   - var flag;
760   -
761   - for (_i = 0; _i < _qCount; _i++) {
762   - for (_j = 0; _j < _internalLpArray.length; _j++) {
763   - _lpObj = _internalLpArray[_j];
764   - _groupObj = _lpObj.getGroup(_i);
765   - // TODO:bug
766   - _bcObj = isUp == _qIsUp ? _groupObj.getBc1() : _groupObj.getBc2();
767   - if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
768   - _bcObj = _fnGenerateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
769   - }
770   - if (_bcObj) {
771   - //console.log("timeobj -> bcobj diff flag " +
772   - // timeObj.format("HH:mm") + "->" +
773   - // _bcObj.getFcTimeObj().format("HH:mm") +
774   - // timeObj.diff(_bcObj.getFcTimeObj()) +
775   - // (timeObj.diff(_bcObj.getFcTimeObj()) <= 0)
776   - //);
777   -
778   - flag = (timeObj.diff(_bcObj.getFcTimeObj())) <= 0;
779   -
780   - if (flag) {
781   - if (!timediff) {
782   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
783   - _lpIndex = _j;
784   - _down_qIndex = _i;
785   - _down_bIndex = isUp == _qIsUp ? 0 : 1;
786   - } else {
787   - if ((timeObj.diff(_bcObj.getFcTimeObj())) > timediff) {
788   - timediff = timeObj.diff(_bcObj.getFcTimeObj());
789   - _lpIndex = _j;
790   - _down_qIndex = _i;
791   - _down_bIndex = isUp == _qIsUp ? 0 : 1;
792   - }
793   - }
794   - }
795   - }
796   - }
797   - }
798   -
799   - if (_lpIndex == undefined) {
800   - return false;
801   - }
802   -
803   - var bcindex = [];
804   - bcindex.push(_lpIndex);
805   - bcindex.push(_down_qIndex);
806   - bcindex.push(_down_bIndex);
807   -
808   - return bcindex;
809   - };
810   -
811   - /**
812   - * 获取班次索引。
813   - * @param oBc 班次对象
814   - * @returns [{路牌索引},{圈索引},{班次索引}]
815   - */
816   - var _fnGetBcIndex = function(oBc) {
817   - // 路牌索引
818   - var i;
819   - var iLpIndex;
820   - for (i = 0; i < _internalLpArray.length; i++) {
821   - if (_internalLpArray[i]._$$_orign_lp_obj == oBc._$$_internal_lp_obj._$$_orign_lp_obj) {
822   - iLpIndex = i;
823   - break;
824   - }
825   - }
826   - // 圈索引
827   - var j;
828   - var iGroupIndex;
829   - var bFlag = false;
830   - for (i = 0; i < _internalLpArray.length; i++) {
831   - if (bFlag) {
832   - break;
833   - }
834   - for (j = 0; j < _qCount; j++) {
835   - if (_internalLpArray[i]._$_groupBcArray[j] == oBc._$$_internal_group_obj) {
836   - iGroupIndex = j;
837   - bFlag = true;
838   - break;
839   - }
840   - }
841   - }
842   - // 班次索引
843   - var iBcIndex = _qIsUp == oBc.isUp() ? 0 : 1;
844   -
845   - if (iLpIndex == undefined) {
846   - return null;
847   - } else {
848   - return [].concat(iLpIndex, iGroupIndex, iBcIndex);
849   - }
850   -
851   - };
852   -
853   - return {
854   - //------------- 布局初始化方法 ------------//
855   - /**
856   - * 初始化数据,使用标线初始化
857   - */
858   - fnInitDataWithBxLayout: function() {
859   - // 初始化布局1,构造上标线,计算圈数,把上标线数据放入第一个路牌中
860   - _fnInitFun1();
861   - // 初始化布局2,从上标线的某个班次开始,构造所有路牌的早高峰班次,晚高峰班次,计算路牌在各个圈中的间隔
862   - _fnInitFun2();
863   - // 初始化布局3,计算连班分班路牌分布
864   - _fnInitFun3();
865   - // 初始化布局4,计算中标线位置
866   - _fnInitFun4();
867   -
868   - },
869   -
870   - /**
871   - * 调整高峰班次,
872   - * 初始化生成早高峰,晚高峰班次并不准确,因为根据高峰时间段,并不在一个完整圈内,应该是在两个或多个圈之间
873   - * 当初始化定好布局后(上标线,中标线),然后确定每个路牌的班型(连班,分班,5休2分班)后
874   - * 然后重新计算框在高峰时间段内的班次索引,不足的添加,之前多加的删除(只删除分班路牌上的)
875   - * @param isZgf 是否早高峰
876   - * @param isUp 是否上行
877   - */
878   - fnAdjustGfbc : function(isZgf, isUp) {
879   - var oStartTime; // 开始时间
880   - var oEndTime; // 结束时间
881   - var aStartBcIndex; // 开始班次索引
882   - var aEndBcIndex; // 结束班次索引
883   -
884   - oStartTime = isZgf ? _paramObj.getMPeakStartTimeObj() : _paramObj.getEPeakStartTimeObj();
885   - oEndTime = isZgf ? _paramObj.getMPeakEndTimeObj() : _paramObj.getEPeakEndTimeObj();
886   -
887   - aStartBcIndex = _fnFindUpClosedBcIndexWithTime(oStartTime, isUp);
888   - aEndBcIndex = _fnFindDownClosedBcIndexWithTime(oEndTime, isUp);
889   -
890   - var iLpIndex;
891   - var iQIndex;
892   - var iBcIndex;
893   - var iQInternelCount; // 高峰时间段中间包含的圈数
894   - var i;
895   - var j;
896   -
897   - var oLp;
898   -
899   - if (aStartBcIndex && aEndBcIndex) {
900   - iLpIndex = aStartBcIndex[0];
901   - iQIndex = aStartBcIndex[1];
902   - iBcIndex = aStartBcIndex[2];
903   -
904   - // 处理头
905   - // 删除头部多余班次
906   - for (j = 0; j < iLpIndex; j++) {
907   - oLp = _internalLpArray[j];
908   - if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
909   - oLp.removeBc(iQIndex, iBcIndex);
910   - }
911   - }
912   -
913   - for (j = iLpIndex; j < _internalLpArray.length; j++) {
914   - oLp = _internalLpArray[j];
915   - if (!oLp.getBc(iQIndex, iBcIndex)) {
916   - _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
917   - }
918   - }
919   -
920   - // 处理中间
921   - iQInternelCount = aEndBcIndex[1] - aStartBcIndex[1] - 1;
922   - for (i = 1; i <= iQInternelCount; i++) {
923   - oLp = _internalLpArray[iQIndex + i];
924   -
925   - if (!oLp.getBc(iQIndex + i, iBcIndex)) {
926   - _fnGenerateBcAndSetBc(i, iQIndex + i, iBcIndex);
927   - }
928   - }
929   -
930   - // 处理尾部
931   - iLpIndex = aEndBcIndex[0];
932   - iQIndex = aEndBcIndex[1];
933   - iBcIndex = aEndBcIndex[2];
934   -
935   - // 删除尾部多余的班次
936   - for (j = iLpIndex; j < _internalLpArray.length; j++) {
937   - oLp = _internalLpArray[j];
938   - if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
939   - oLp.removeBc(iQIndex, iBcIndex);
940   - }
941   - }
942   -
943   - if (aStartBcIndex[1] != aEndBcIndex[1]) { // 指定时间范围跨圈
944   - for (j = 0; j < iLpIndex; j++) {
945   - oLp = _internalLpArray[j];
946   - if (!oLp.getBc(iQIndex, iBcIndex)) {
947   - _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
948   - }
949   - }
950   - } else {
951   - // 不跨圈,不用处理,处理头的时候已经加了
952   - }
953   -
954   - }
955   -
956   - },
957   -
958   - /**
959   - * 按照营运时间要求补充班次,
960   - * 早高峰7:45分以前出场运营,
961   - * 晚高峰16:10分以前出场运营
962   - */
963   - fnCalcuLpBc_yy: function() {
964   - // 补班次的时候,针对的是分班班型
965   - var i;
966   - var _oLp;
967   - var _oBc;
968   - var _aMinBcIndex;
969   - var _aMaxBcIndex;
970   -
971   - var _qIndex;
972   - var _bIndex;
973   -
974   - var _zgfCDate = _paramObj.toTimeObj("7:45");
975   - var _wgfCDate = _paramObj.toTimeObj("16:10");
976   - var _ccsj;
977   -
978   - for (i = 0; i < _internalLpArray.length; i++) {
979   - _oLp = _internalLpArray[i];
980   - if (_oLp.isBxFb()) { // 分班路牌
981   - // 早高峰部分
982   - _aMinBcIndex = _oLp.getMinBcObjPosition();
983   - _qIndex = _aMinBcIndex[0];
984   - _bIndex = _aMinBcIndex[1];
985   - _oBc = _oLp.getBc(_qIndex, _bIndex);
986   - if (_qIsUp) {
987   - _ccsj = _bIndex == 0 ?
988   - _paramObj.getUpOutTime() :
989   - _paramObj.getDownOutTime();
990   - } else {
991   - _ccsj = _bIndex == 0 ?
992   - _paramObj.getDownOutTime() :
993   - _paramObj.getUpOutTime();
994   - }
995   - if (_zgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
996   - _fnGenerateBcAndSetBc(
997   - i,
998   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
999   - _bIndex == 0 ? 1 : 0
1000   - )
1001   - }
1002   -
1003   - // 晚高峰部分
1004   - _aMaxBcIndex = _oLp.getMaxBcObjPosition();
1005   - _qIndex = _aMaxBcIndex[0];
1006   - _bIndex = _aMaxBcIndex[1];
1007   - _oBc = _oLp.getBc(
1008   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
1009   - _bIndex == 0 ? 1 : 0
1010   - );
1011   - if (!_oBc) { // 前一个班次不存在,再判定加不加
1012   - _oBc = _oLp.getBc(_qIndex, _bIndex);
1013   - if (_qIsUp) {
1014   - _ccsj = _bIndex == 0 ?
1015   - _paramObj.getUpOutTime() :
1016   - _paramObj.getDownOutTime();
1017   - } else {
1018   - _ccsj = _bIndex == 0 ?
1019   - _paramObj.getDownOutTime() :
1020   - _paramObj.getUpOutTime();
1021   - }
1022   - if (_wgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
1023   - _fnGenerateBcAndSetBc(
1024   - i,
1025   - _bIndex == 0 ? _qIndex - 1 : _qIndex,
1026   - _bIndex == 0 ? 1 : 0
1027   - )
1028   - }
1029   - }
1030   - }
1031   - }
1032   - },
1033   -
1034   - /**
1035   - * 补充做5休2的班型班次。
1036   - * 1、确认5_2班型大致多少圈(小数点过.7进位)
1037   - * 2、获取当前5_2两端车次链的信息,每段的班次数目,还差几个班次没加
1038   - * 3、如果前面的车次链班次少,则从前面的车次链开始加
1039   - * 4、如果车次链班次数一样,从从后面的车次链开始加
1040   - * 5、加班次时都是往车次链前方加
1041   - * 6、如果前面车次链不能再加班次了,从后面车次链加
1042   - */
1043   - fnCalcuLpBx_5_2: function() {
1044   - // 计算做5休2班型所需的班次数
1045   - var iBxBcount = _aBxDesc[6].fBcCount;
1046   - if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
1047   - iBxBcount = Math.floor(iBxBcount) + 1;
1048   - } else {
1049   - iBxBcount = Math.floor(iBxBcount);
1050   - }
1051   -
1052   - var i;
1053   - var j;
1054   - var oLp;
1055   - var iAddBcCount;
1056   - var oBcChain1;
1057   - var oBcChain2;
1058   - var iQindex;
1059   - var iBindex;
1060   -
1061   - for (i = 0; i < _internalLpArray.length; i++) {
1062   - oLp = _internalLpArray[i];
1063   - if (oLp.isBxFb5_2()) {
1064   - iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
1065   - for (j = 1; j <= iAddBcCount; j++) {
1066   - oBcChain1 = oLp.fnGetBcChainInfo(0);
1067   - oBcChain2 = oLp.fnGetBcChainInfo(1);
1068   -
1069   - if (oBcChain1.bcount < oBcChain2.bcount) {
1070   - iQindex = oBcChain1.s_b == 0 ? oBcChain1.s_q - 1 : oBcChain1.s_q;
1071   - iBindex = oBcChain1.s_b == 0 ? 1 : 0;
1072   - // 往车次链往前不能加,就往后加
1073   - if (_fnGenerateBc(i, iQindex, iBindex)) {
1074   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1075   - } else {
1076   - iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
1077   - iBindex = oBcChain1.e_b == 0 ? 1 : 0;
1078   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1079   - }
1080   -
1081   - } else if (oBcChain1.bcount > oBcChain2.bcount) {
1082   - iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
1083   - iBindex = oBcChain2.s_b == 0 ? 1 : 0;
1084   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1085   - } else {
1086   - iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
1087   - iBindex = oBcChain2.s_b == 0 ? 1 : 0;
1088   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1089   - }
1090   - }
1091   - }
1092   - }
1093   -
1094   - },
1095   -
1096   - /**
1097   - * 补其他分班班型班次。
1098   - * 从车次链的后面开始加
1099   - */
1100   - fnCalcuLpBx_other: function() {
1101   - // TODO:根据上标线的首班时间确定班型,小于05:59的做一休一,否则做二休一
1102   - var oSt = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
1103   - var iBxIndex = 4;
1104   - if (oSt.isBefore(_paramObj.toTimeObj("05:59"))) {
1105   - iBxIndex = 5;
1106   - }
1107   - // 计算做5休2班型所需的班次数
1108   - var iQBcount = _aBxDesc[iBxIndex].fQCount;
1109   - var iBxBcount = Math.round(iQBcount) * 2;
1110   -
1111   - var i;
1112   - var j;
1113   - var oLp;
1114   - var iAddBcCount;
1115   - var oBcChain1;
1116   - var oBcChain2;
1117   - var iQindex;
1118   - var iBindex;
1119   -
1120   - for (i = 0; i < _internalLpArray.length; i++) {
1121   - oLp = _internalLpArray[i];
1122   - if (oLp.isBxFb() && !oLp.isBxFb5_2()) {
1123   - iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
1124   - for (j = 1; j <= iAddBcCount; j++) {
1125   - oBcChain1 = oLp.fnGetBcChainInfo(0);
1126   - oBcChain2 = oLp.fnGetBcChainInfo(1);
1127   -
1128   - if (oBcChain1.bcount < oBcChain2.bcount) {
1129   - iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
1130   - iBindex = oBcChain1.e_b == 0 ? 1 : 0;
1131   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1132   - } else if (oBcChain1.bcount > oBcChain2.bcount) {
1133   - iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
1134   - iBindex = oBcChain2.e_b == 0 ? 1 : 0;
1135   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1136   - } else {
1137   - iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
1138   - iBindex = oBcChain2.e_b == 0 ? 1 : 0;
1139   - _fnGenerateBcAndSetBc(i, iQindex, iBindex);
1140   - }
1141   - }
1142   - }
1143   - }
1144   -
1145   - },
1146   -
1147   - /**
1148   - * 补充连班路牌班次。
1149   - * 1、上标线,中标线中间的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向上标线起始班次靠拢
1150   - * 2、中标线以下的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向中标线起始班次靠拢
1151   - */
1152   - fnCalcuLpBx_lb: function() {
1153   - // 补充连班的班次,参照上标线,中标线补充不足的班次
1154   -
1155   - var aLbLpindexes = []; // 除上标线,中标线的连班路牌索引
1156   - var i;
1157   - for (i = 0; i < _internalLpArray.length; i++) {
1158   - if (_internalLpArray[i].isBxLb() && i != 0 && i != _iZbx_lpIndex) {
1159   - aLbLpindexes.push(i);
1160   - }
1161   - }
1162   -
1163   - var oEndsj = // 结束时间
1164   - _paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj()) ?
1165   - _paramObj.getDownLastDTimeObj() :
1166   - _paramObj.getUpLastDtimeObj();
1167   -
1168   - var oLp;
1169   - var aMinbcPos;
1170   - var oBc;
1171   - var j;
1172   - var iTempBcIndex;
1173   -
1174   - // 1、从最小班次开始,往后补充班次
1175   - for (i = 0; i < aLbLpindexes.length; i++) {
1176   - oLp = _internalLpArray[aLbLpindexes[i]];
1177   -
1178   - // 最小班次索引
1179   - aMinbcPos = oLp.getMinBcObjPosition();
1180   - // 使用纵向分隔补充班次,从最小班次向后补
1181   - iTempBcIndex = aMinbcPos[1] == 0 ? 1 : 0;
1182   - j = iTempBcIndex == 0 ? aMinbcPos[0] + 1 : aMinbcPos[0];
1183   -
1184   - while (j < _qCount) {
1185   - while (iTempBcIndex <= 1) {
1186   - oBc = _fnGenerateBc(aLbLpindexes[i], j, iTempBcIndex);
1187   - if (oBc &&
1188   - oBc.getFcTimeObj().isBefore(oEndsj) ) {
1189   - oLp.setBc(j, iTempBcIndex, oBc);
1190   - }
1191   - iTempBcIndex++;
1192   - }
1193   - iTempBcIndex = 0;
1194   - j++;
1195   - }
1196   -
1197   - }
1198   -
1199   - // 2、上标线中标线之间的路牌,从最小的班次往前补充班次
1200   -
1201   - // 还要补充缺失的班次,差上标线几个班次要往前补上
1202   - var iBccount;
1203   - var iQindex;
1204   - var iBindex;
1205   - // 补上标线到中标线之间的连班路牌的班次
1206   - for (i = 0; i < aLbLpindexes.length; i++) {
1207   - if (aLbLpindexes[i] > 0 && aLbLpindexes[i] < _iZbx_lpIndex) {
1208   - oLp = _internalLpArray[aLbLpindexes[i]];
1209   - aMinbcPos = oLp.getMinBcObjPosition();
1210   - iQindex = aMinbcPos[0];
1211   - iBindex = aMinbcPos[1];
1212   - iBccount = (iQindex - 1) * 2 + iBindex; // 距离上标线起始站点差几个班次
1213   - for (j = 0; j < iBccount; j++) {
1214   - if (iBindex == 0) {
1215   - iQindex --;
1216   - iBindex = 1;
1217   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1218   - } else if (iBindex == 1) {
1219   - iBindex --;
1220   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1221   - }
1222   - }
1223   -
1224   - }
1225   -
1226   - }
1227   -
1228   - // 3、中标线之后的路牌,从最小的班次往前补充班次
1229   -
1230   - // 补中标线以下的连班路牌的班次
1231   - for (i = 0; i < aLbLpindexes.length; i++) {
1232   - if (aLbLpindexes[i] > _iZbx_lpIndex) {
1233   - oLp = _internalLpArray[aLbLpindexes[i]];
1234   - aMinbcPos = oLp.getMinBcObjPosition();
1235   - iQindex = aMinbcPos[0];
1236   - iBindex = aMinbcPos[1];
1237   - iBccount = (iQindex - 0) * 2 + iBindex - 1; // 距离上标线起始站点差几个班次
1238   - for (j = 0; j < iBccount; j++) {
1239   - if (iBindex == 0) {
1240   - iQindex --;
1241   - iBindex = 1;
1242   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1243   - } else if (iBindex == 1) {
1244   - iBindex --;
1245   - _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
1246   - }
1247   - }
1248   - }
1249   - }
1250   -
1251   - },
1252   -
1253   - /**
1254   - * 计算末班车。
1255   - * 1、将上下行拉成上下行两个班次列表(包括标记班次)
1256   - * 2、分别找出离末班车发车时间最近的班次,并替换时间
1257   - * 3、删除之后的班次
1258   - */
1259   - fnCalcuLastBc: function() {
1260   - var i;
1261   - var iTimeDiff;
1262   - var iTempTime;
1263   - var aBc;
1264   - var oLastBcTime;
1265   - var oLastBcIsUp;
1266   - var iModifyIndex;
1267   -
1268   - // 查找末班车早的末班车时间和方向
1269   - if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
1270   - oLastBcTime = _paramObj.getUpLastDtimeObj();
1271   - oLastBcIsUp = true;
1272   - } else {
1273   - oLastBcTime = _paramObj.getDownLastDTimeObj();
1274   - oLastBcIsUp = false;
1275   - }
1276   -
1277   - // 确定早的末班车时间
1278   - aBc = _fnGetBcList(oLastBcIsUp);
1279   - for (i = 0; i < aBc.length; i++) {
1280   - iTempTime = oLastBcTime.diff(aBc[i].getFcTimeObj(), "m");
1281   - if (iTimeDiff == undefined) {
1282   - iTimeDiff = iTempTime;
1283   - iModifyIndex = i;
1284   - } else if (Math.abs(iTempTime) <= Math.abs(iTimeDiff)) {
1285   - iTimeDiff = iTempTime;
1286   - iModifyIndex = i;
1287   - }
1288   - }
1289   - aBc[iModifyIndex].addMinuteToFcsj(iTimeDiff); // 替换成末班车时间
1290   - aBc[iModifyIndex].fnSetDelFlag(false);
1291   - for (i = iModifyIndex + 1; i < aBc.length; i++) { // 删除多余班次
1292   - _qIsUp == oLastBcIsUp ?
1293   - aBc[i]._$$_internal_group_obj.setBc1(undefined) :
1294   - aBc[i]._$$_internal_group_obj.setBc2(undefined);
1295   - }
1296   -
1297   - // 查找末班车晚的末班车时间和方向
1298   - if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
1299   - oLastBcTime = _paramObj.getDownLastDTimeObj();
1300   - oLastBcIsUp = false;
1301   - } else {
1302   - oLastBcTime = _paramObj.getUpLastDtimeObj();
1303   - oLastBcIsUp = true;
1304   - }
1305   - // 确定晚的末班车时间
1306   - aBc = _fnGetBcList(oLastBcIsUp);
1307   - var oBc;
1308   - var aBcIndex;
1309   - var iLpIndex;
1310   - var iQIndex;
1311   - var iBcIndex;
1312   -
1313   - iTimeDiff = undefined;
1314   - for (i = 0; i < aBc.length; i++) {
1315   - oBc = aBc[i];
1316   - aBcIndex = _fnGetBcIndex(oBc);
1317   -
1318   - iLpIndex = aBcIndex[0];
1319   - iQIndex = aBcIndex[2] == 0 ? aBcIndex[1] -1 : aBcIndex[1];
1320   - iBcIndex = aBcIndex[2] == 0 ? 1 : 0;
1321   -
1322   - if (!_internalLpArray[iLpIndex].getBc(iQIndex, iBcIndex)) {
1323   - continue;
1324   - }
1325   -
1326   - iTempTime = oLastBcTime.diff(aBc[i].getFcTimeObj(), "m");
1327   - if (iTimeDiff == undefined) {
1328   - iTimeDiff = iTempTime;
1329   - iModifyIndex = i;
1330   - } else if (Math.abs(iTempTime) <= Math.abs(iTimeDiff)) {
1331   - iTimeDiff = iTempTime;
1332   - iModifyIndex = i;
1333   - }
1334   - }
1335   - aBc[iModifyIndex].addMinuteToFcsj(iTimeDiff); // 替换成末班车时间
1336   - aBc[iModifyIndex].fnSetDelFlag(false);
1337   - for (i = iModifyIndex + 1; i < aBc.length; i++) { // 删除多余班次
1338   - _qIsUp == oLastBcIsUp ?
1339   - aBc[i]._$$_internal_group_obj.setBc1(undefined) :
1340   - aBc[i]._$$_internal_group_obj.setBc2(undefined);
1341   - }
1342   -
1343   - },
1344   -
1345   - /**
1346   - * 添加吃饭班次。
1347   - */
1348   - fnCalcuEatBc: function() {
1349   - // 吃午饭时间范围,10:15 到 12:15
1350   - // 吃晚饭时间范围,18:00 到 19:00
1351   -
1352   - if (!_paramObj.fnIsEat()) {
1353   - return;
1354   - }
1355   -
1356   - // 午饭index
1357   - var aLEIndex;
1358   - // 晚饭index
1359   - var aDEIndex;
1360   -
1361   - // 所有吃饭都默认在一个方向,两个方向暂时不考虑
1362   - if (_paramObj.fnIsUpEat()) {
1363   - aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), true, false);
1364   - aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), true, false);
1365   - } else {
1366   - aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), false, true);
1367   - aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), false, true);
1368   - }
1369   -
1370   - // 午饭第几圈,第几个班次
1371   - var iLEQIndex = aLEIndex[0];
1372   - var iLEBIndex = aLEIndex[1];
1373   - // 晚饭第几圈,第几个班次
1374   - var iDEQIndex = aDEIndex[0];
1375   - var iDEBIndex = aDEIndex[1];
1376   -
1377   - // 注意,本模型只有连班才有吃饭
1378   -
1379   - var i;
1380   - var oLp;
1381   - var aLbIndex = []; // 连班班型的路牌索引
1382   - for (i = 0; i < _internalLpArray.length; i++) {
1383   - oLp = _internalLpArray[i];
1384   - if (oLp.isBxLb()) {
1385   - aLbIndex.push(i);
1386   - }
1387   - }
1388   -
1389   - var iLTime;
1390   - var iDtime;
1391   - var j;
1392   - for (i = 0; i < aLbIndex.length; i++) {
1393   - oLp = _internalLpArray[aLbIndex[i]];
1394   -
1395   - // 午饭
1396   - iLTime = oLp.fnAddEatBc(iLEQIndex, iLEBIndex, _factory, _paramObj);
1397   - // 晚饭
1398   - iDtime = oLp.fnAddEatBc(iDEQIndex, iDEBIndex, _factory, _paramObj);
1399   -
1400   - if (i == aLbIndex.length - 1) {
1401   - for (j = aLbIndex[i]; j < _internalLpArray.length; j++) {
1402   - oLp = _internalLpArray[j];
1403   - if (oLp.isBxFb()) { // 5休2班型不调整
1404   - // 修正午饭之后路牌班次的发车时间
1405   - oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
1406   - oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
1407   - }
1408   - }
1409   - } else {
1410   - for (j = aLbIndex[i]; j < aLbIndex[i + 1]; j++) {
1411   - oLp = _internalLpArray[j];
1412   - if (oLp.isBxFb()) {
1413   - // 修正午饭之后路牌班次的发车时间
1414   - oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
1415   - oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
1416   - }
1417   - }
1418   - }
1419   - }
1420   -
1421   - },
1422   -
1423   - /**
1424   - * 补每个路牌的其他班次(进出场,例保班次)。
1425   - */
1426   - fnCalcuOtherBc_: function() {
1427   - var i;
1428   - var _lpObj;
1429   - var _minBcIndex;
1430   - var _maxBcIndex;
1431   - var _minBc;
1432   - var _maxBc;
1433   - var _otherbc = [];
1434   - var _oFbbc;
1435   -
1436   - for (i = 0; i < _internalLpArray.length; i++) {
1437   - _lpObj = _internalLpArray[i];
1438   - _minBcIndex = _lpObj.getMinBcObjPosition();
1439   - _maxBcIndex = _lpObj.getMaxBcObjPosition();
1440   - _minBc = _lpObj.getBc(_minBcIndex[0], _minBcIndex[1]);
1441   - _maxBc = _lpObj.getBc(_maxBcIndex[0], _maxBcIndex[1]);
1442   -
1443   - _otherbc = [];
1444   - _otherbc.push(_factory.createBcObj(
1445   - _lpObj, "bd", true, 1,
1446   - _minBc.getFcTimeObj(),
1447   - _paramObj
1448   - ));
1449   - _otherbc.push(_factory.createBcObj(
1450   - _lpObj, "out", true, 1,
1451   - _minBc.getFcTimeObj(),
1452   - _paramObj
1453   - ));
1454   -
1455   - _maxBc.setArrTimeObj(_paramObj.addMinute(_maxBc.getFcTimeObj(), _maxBc.getBcTime()));
1456   - _maxBc.setStopTime(0);
1457   - _otherbc.push(_factory.createBcObj(
1458   - _lpObj, "in", true, 1,
1459   - _maxBc.getArrTimeObj(),
1460   - _paramObj
1461   - ));
1462   - _otherbc.push(_factory.createBcObj(
1463   - _lpObj, "lc", true, 1,
1464   - _maxBc.getArrTimeObj(),
1465   - _paramObj
1466   - ));
1467   -
1468   - // 5休2分班出场例保班次
1469   - if (_lpObj.isBxFb5_2()) {
1470   - _oFbbc = _lpObj.getBc(
1471   - _lpObj.fnGetBcChainInfo(1)["s_q"],
1472   - _lpObj.fnGetBcChainInfo(1)["s_b"]
1473   - );
1474   -
1475   - _otherbc.push(_factory.createBcObj(
1476   - _lpObj, "bd", true, 1,
1477   - _oFbbc.getFcTimeObj(),
1478   - _paramObj
1479   - ));
1480   - _otherbc.push(_factory.createBcObj(
1481   - _lpObj, "out", true, 1,
1482   - _oFbbc.getFcTimeObj(),
1483   - _paramObj
1484   - ));
1485   - }
1486   -
1487   - _lpObj.addOtherBcArray(_otherbc);
1488   - }
1489   -
1490   - },
1491   -
1492   - /**
1493   - * 补每个路牌的其他班次(进出场,例保班次)
1494   - * 所有的车次链前后都加进出场、报道班次
1495   - */
1496   - fnCalcuOtherBc: function() {
1497   - var i;
1498   - var j;
1499   - var iBcChainCount;
1500   - var oLp;
1501   - var aOtherBc;
1502   - var oStartBc;
1503   - var oEndBc;
1504   -
1505   - for (i = 0; i < _internalLpArray.length; i++) {
1506   - aOtherBc = [];
1507   - oLp = _internalLpArray[i];
1508   - iBcChainCount = oLp.fnGetBcChainCount();
1509   -
1510   - if (iBcChainCount == 1) { // 只有一个车次链,是连班班型
1511   - // 头部要添加出场,例保班次
1512   - oStartBc = oLp.getBc(
1513   - oLp.fnGetBcChainInfo(0)["s_q"],
1514   - oLp.fnGetBcChainInfo(0)["s_b"]
1515   - );
1516   - aOtherBc.push(_factory.createBcObj(
1517   - oLp, "bd", true, 1,
1518   - oStartBc.getFcTimeObj(),
1519   - _paramObj
1520   - ));
1521   - aOtherBc.push(_factory.createBcObj(
1522   - oLp, "out", true, 1,
1523   - oStartBc.getFcTimeObj(),
1524   - _paramObj
1525   - ));
1526   -
1527   - // 尾部需添加进场,例保班次
1528   - oEndBc = oLp.getBc(
1529   - oLp.fnGetBcChainInfo(0)["e_q"],
1530   - oLp.fnGetBcChainInfo(0)["e_b"]
1531   - );
1532   - aOtherBc.push(_factory.createBcObj(
1533   - oLp, "in", true, 1,
1534   - oEndBc.getArrTimeObj(),
1535   - _paramObj
1536   - ));
1537   - aOtherBc.push(_factory.createBcObj(
1538   - oLp, "lc", true, 1,
1539   - oEndBc.getArrTimeObj(),
1540   - _paramObj
1541   - ));
1542   - } else if (iBcChainCount == 2) { // 两个车次链,是分班班型
1543   - // 第一个车次链开头有出场,报到班次,车次链结尾只有进场班次
1544   - oStartBc = oLp.getBc(
1545   - oLp.fnGetBcChainInfo(0)["s_q"],
1546   - oLp.fnGetBcChainInfo(0)["s_b"]
1547   - );
1548   - aOtherBc.push(_factory.createBcObj(
1549   - oLp, "bd", true, 1,
1550   - oStartBc.getFcTimeObj(),
1551   - _paramObj
1552   - ));
1553   - aOtherBc.push(_factory.createBcObj(
1554   - oLp, "out", true, 1,
1555   - oStartBc.getFcTimeObj(),
1556   - _paramObj
1557   - ));
1558   -
1559   - oEndBc = oLp.getBc(
1560   - oLp.fnGetBcChainInfo(0)["e_q"],
1561   - oLp.fnGetBcChainInfo(0)["e_b"]
1562   - );
1563   - aOtherBc.push(_factory.createBcObj(
1564   - oLp, "in", true, 1,
1565   - oEndBc.getArrTimeObj(),
1566   - _paramObj
1567   - ));
1568   -
1569   - // 第二个车次链开头只有出场班次,车次链结尾有进场,报到班次
1570   - oStartBc = oLp.getBc(
1571   - oLp.fnGetBcChainInfo(1)["s_q"],
1572   - oLp.fnGetBcChainInfo(1)["s_b"]
1573   - );
1574   - aOtherBc.push(_factory.createBcObj(
1575   - oLp, "out", true, 1,
1576   - oStartBc.getFcTimeObj(),
1577   - _paramObj
1578   - ));
1579   -
1580   - oEndBc = oLp.getBc(
1581   - oLp.fnGetBcChainInfo(1)["e_q"],
1582   - oLp.fnGetBcChainInfo(1)["e_b"]
1583   - );
1584   - aOtherBc.push(_factory.createBcObj(
1585   - oLp, "in", true, 1,
1586   - oEndBc.getArrTimeObj(),
1587   - _paramObj
1588   - ));
1589   - aOtherBc.push(_factory.createBcObj(
1590   - oLp, "lc", true, 1,
1591   - oEndBc.getArrTimeObj(),
1592   - _paramObj
1593   - ));
1594   -
1595   -
1596   - } else {
1597   - // 2个车次链以上,暂时没有此班型
1598   - }
1599   -
1600   - oLp.addOtherBcArray(aOtherBc);
1601   - }
1602   - },
1603   -
1604   - /**
1605   - * 祛除上标线开头的删除标记的班次。
1606   - */
1607   - fnRemoveDelFirstFlagBc: function() {
1608   - var oLp = _internalLpArray[0];
1609   - var aMinBcIndex = oLp.getMinBcObjPosition();
1610   - oLp.removeBc(aMinBcIndex[0], aMinBcIndex[1]);
1611   - },
1612   - /**
1613   - * 祛除上标线结尾的删除标记的班次。
1614   - */
1615   - fnRemoveDelLastFlagBc: function() {
1616   - var oLp = _internalLpArray[0];
1617   - var aMaxBcIndex = oLp.getMaxBcObjPosition();
1618   - if (oLp.getBc(aMaxBcIndex[0], aMaxBcIndex[1]).fnIsDelFlag()) {
1619   - oLp.removeBc(aMaxBcIndex[0], aMaxBcIndex[1]);
1620   - }
1621   - },
1622   -
1623   - /**
1624   - * 调整路牌班次间隔(核准周转时间,停站时间)。
1625   - * @param iFre int 迭代次数
1626   - */
1627   - fnAdjustLpBcInterval: function(iFre) {
1628   - if (iFre > 0) {
1629   - for (var i = 0; i < _internalLpArray.length; i++) {
1630   - _internalLpArray[i].fnAdjustBcInterval(
1631   - this.fnCalcuAverPeakStopTime(),
1632   - this.fnCalcuAverTroughStopTime(),
1633   - _paramObj);
1634   - }
1635   -
1636   - this.fnAdjustLpBcInterval(iFre - 1);
1637   - }
1638   - },
1639   -
1640   - /**
1641   - * 调整班次间隔。
1642   - * @param bIsUp 是否上行
1643   - * @param oStartTime 开始时间对象
1644   - * @param iFre 迭代次数
1645   - */
1646   - fnAdjustBcInterval2_: function(bIsUp, oStartTime, iFre) {
1647   - if (iFre > 0) {
1648   - var aBc = _fnGetBcList2(bIsUp, oStartTime); // 指定方向的班次列表
1649   - aBc.sort(function(o1, o2) {
1650   - if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
1651   - return -1;
1652   - } else {
1653   - return 1;
1654   - }
1655   - });
1656   - var i;
1657   - var j;
1658   -
1659   - var iBcCountOfGroup = 3; // 3个班次取一次计算
1660   - var aBcOfGroup; // 3个班次列表
1661   - var aBcIntervalOfGroup; // 班次间隔列表,如:3个班次,2个间隔
1662   -
1663   - for (i = 0; i <= aBc.length - iBcCountOfGroup; i++) {
1664   - aBcOfGroup = [];
1665   - aBcIntervalOfGroup = [];
1666   - for (j = i; j < i + iBcCountOfGroup; j++) {
1667   - aBcOfGroup.push(aBc[j]);
1668   - }
1669   -
1670   - for (j = 0; j < aBcOfGroup.length; j++) {
1671   - if (j < aBcOfGroup.length - 1) {
1672   - aBcIntervalOfGroup.push(aBcOfGroup[j + 1].getFcTimeObj().diff(
1673   - aBcOfGroup[j].getFcTimeObj(), "m"));
1674   - }
1675   - }
1676   -
1677   - if (aBcIntervalOfGroup[0] < 19) {
1678   - aBcOfGroup[1].addMinuteToFcsj(1);
1679   - } else if (aBcIntervalOfGroup[0] > 20) {
1680   - aBcOfGroup[1].addMinuteToFcsj(-1);
1681   - } else {
1682   - if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
1683   - //continue;
1684   - } else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
1685   - aBcOfGroup[1].addMinuteToFcsj(-1);
1686   - } else {
1687   - aBcOfGroup[1].addMinuteToFcsj(1);
1688   - }
1689   - }
1690   -
1691   - }
1692   -
1693   - this.fnAdjustBcInterval2(bIsUp, oStartTime, iFre - 1);
1694   - }
1695   - },
1696   -
1697   - /**
1698   - * 调整班次间隔。
1699   - * @param boolean isUp 是否上行
1700   - * @param oStartTime 开始时间对象
1701   - * @param fre int 迭代次数
1702   - */
1703   - fnAdjustBcInterval: function(isUp, oStartTime, fre) {
1704   - if (fre > 0) {
1705   - var aBc = !oStartTime ? _fnGetBcList(isUp) : _fnGetBcList2(isUp, oStartTime); // 指定方向的班次列表
1706   -
1707   - aBc.sort(function(o1, o2) {
1708   - if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
1709   - return -1;
1710   - } else {
1711   - return 1;
1712   - }
1713   - });
1714   -
1715   - var i;
1716   - var j;
1717   -
1718   - var iBcCountOfGroup = 3; // 3个班次取一次计算
1719   - var aBcOfGroup; // 3个班次列表
1720   - var aBcIntervalOfGroup; // 班次间隔列表,如:3个班次,2个间隔
1721   - var oBcFcTime; // 班次发车时间
1722   -
1723   - for (i = 0; i <= aBc.length - iBcCountOfGroup; i++) {
1724   - aBcOfGroup = [];
1725   - aBcIntervalOfGroup = [];
1726   - for (j = i; j < i + iBcCountOfGroup; j++) {
1727   - aBcOfGroup.push(aBc[j]);
1728   - }
1729   -
1730   - for (j = 0; j < aBcOfGroup.length; j++) {
1731   - if (j < aBcOfGroup.length - 1) {
1732   - aBcIntervalOfGroup.push(aBcOfGroup[j + 1].getFcTimeObj().diff(
1733   - aBcOfGroup[j].getFcTimeObj(), "m"));
1734   - }
1735   - }
1736   -
1737   - // 判定规则
1738   - oBcFcTime = aBcOfGroup[1].getFcTimeObj();
1739   -
1740   - // 第一个班次发车时间不动,根据间隔,调整中间一个班次
1741   - // 如果3个班次2个间隔时间差1分钟,不调整
1742   - // 如果第一个间隔大,调整第二个班次往前1分钟
1743   - // 如果第二个间隔大,调整第二个班次往后1分钟
1744   -
1745   - if (_paramObj.isTroughBc(oBcFcTime) &&
1746   - aBcIntervalOfGroup[0] > _paramObj.getTroughMaxFcjx()) {
1747   - aBcOfGroup[1].addMinuteToFcsj(-1);
1748   - }
1749   -
1750   - //else if (_paramObj.isMPeakBc(oBcFcTime) &&
1751   - // aBcIntervalOfGroup[0] < _paramObj.getMPeakMinFcjx()) {
1752   - // aBcOfGroup[1].addMinuteToFcsj(1);
1753   - //} else if (_paramObj.isMPeakBc(oBcFcTime) &&
1754   - // aBcIntervalOfGroup[0] > _paramObj.getMPeakMaxFcjx()) {
1755   - // aBcOfGroup[1].addMinuteToFcsj(-1);
1756   - //} else if (_paramObj.isEPeakBc(oBcFcTime) &&
1757   - // aBcIntervalOfGroup[0] < _paramObj.getEPeakMinFcjx()) {
1758   - // aBcOfGroup[1].addMinuteToFcsj(1);
1759   - //} else if (_paramObj.isEPeakBc(oBcFcTime) &&
1760   - // aBcIntervalOfGroup[0] > _paramObj.getEPeakMaxFcjx()) {
1761   - // aBcOfGroup[1].addMinuteToFcsj(-1);
1762   - //}
1763   -
1764   -
1765   - else {
1766   - if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
1767   - //continue;
1768   - } else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
1769   - aBcOfGroup[1].addMinuteToFcsj(-1);
1770   - } else {
1771   - aBcOfGroup[1].addMinuteToFcsj(1);
1772   - }
1773   - }
1774   -
1775   - //if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
1776   - // //continue;
1777   - //} else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
1778   - // aBcOfGroup[1].addMinuteToFcsj(-1);
1779   - //} else {
1780   - // aBcOfGroup[1].addMinuteToFcsj(1);
1781   - //}
1782   -
1783   -
1784   - }
1785   -
1786   - this.fnAdjustBcInterval(isUp, oStartTime, fre - 1);
1787   - }
1788   -
1789   - },
1790   -
1791   - /**
1792   - * 调整班次间隔(平均间隔)。
1793   - * @param bIsUp 是否上行
1794   - * @param oStartTime 开始时间对象
1795   - */
1796   - fnAdjustBcInterval2_avg: function(bIsUp, oStartTime) {
1797   - var aBc = !oStartTime ? _fnGetBcList(bIsUp) : _fnGetBcList2(bIsUp, oStartTime); // 指定方向的班次列表
1798   - aBc.sort(function(o1, o2) {
1799   - if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
1800   - return -1;
1801   - } else {
1802   - return 1;
1803   - }
1804   - });
1805   -
1806   - var j;
1807   - var iCount = aBc.length - 1;
1808   - var iC1 = Math.floor(aBc[aBc.length - 1].getFcTimeObj().diff(aBc[0].getFcTimeObj(), "m") / iCount);
1809   - var iC2 = aBc[aBc.length - 1].getFcTimeObj().diff(aBc[0].getFcTimeObj(), "m") % iCount;
1810   - var iTempTime;
1811   -
1812   - for (j = 0; j < iCount - iC2; j++) {
1813   - iTempTime = aBc[j + 1].getFcTimeObj().diff(aBc[j].getFcTimeObj(), "m");
1814   - aBc[j + 1].addMinuteToFcsj(iC1 - iTempTime);
1815   - }
1816   - for (j = 0; j < iC2; j++) {
1817   - iTempTime = aBc[iCount - iC2 + j + 1].getFcTimeObj().diff(aBc[iCount - iC2 + j].getFcTimeObj(), "m");
1818   - aBc[iCount - iC2 + j + 1].addMinuteToFcsj(iC1 + 1 - iTempTime);
1819   - }
1820   -
1821   - },
1822   -
1823   - /**
1824   - * 计算高峰平均停站时间。
1825   - */
1826   - fnCalcuAverPeakStopTime: function() {
1827   - var i;
1828   - var j;
1829   - var aBc;
1830   - var iBcCount = 0;
1831   - var iSum = 0;
1832   - for (i = 0; i < _internalLpArray.length; i++) {
1833   - aBc = _internalLpArray[i].getBcArray();
1834   -
1835   - for (j = 0; j < aBc.length; j++) {
1836   - if (!_paramObj.isTroughBc(aBc[j].getArrTimeObj())) {
1837   - iBcCount ++;
1838   - iSum += aBc[j].getStopTime();
1839   - }
1840   - }
1841   - }
1842   -
1843   - return Math.floor(iSum / iBcCount);
1844   - },
1845   -
1846   - /**
1847   - * 计算低谷平均停站时间。
1848   - */
1849   - fnCalcuAverTroughStopTime: function() {
1850   - var i;
1851   - var j;
1852   - var aBc;
1853   - var iBcCount = 0;
1854   - var iSum = 0;
1855   - for (i = 0; i < _internalLpArray.length; i++) {
1856   - aBc = _internalLpArray[i].getBcArray();
1857   - for (j = 0; j < aBc.length; j++) {
1858   - if (_paramObj.isTroughBc(aBc[j].getArrTimeObj())) {
1859   - iBcCount ++;
1860   - iSum += aBc[j].getStopTime();
1861   - }
1862   - }
1863   - }
1864   -
1865   - return Math.floor(iSum / iBcCount);
1866   - },
1867   -
1868   - //------------- 其他方法 -------------//
1869   - /**
1870   - * 内部数据转化成显示用的班次数组。
1871   - */
1872   - fnToGanttBcArray: function() {
1873   - var aAllBc = [];
1874   - var aLpBc = [];
1875   - var aEatBc = [];
1876   - var oLp;
1877   - var i;
1878   - var j;
1879   -
1880   - for (i = 0; i < _internalLpArray.length; i++) {
1881   - oLp = _internalLpArray[i];
1882   - aLpBc = [];
1883   - aLpBc = aLpBc.concat(oLp.getOtherBcArray(), oLp.getBcArray());
1884   -
1885   - aEatBc = [];
1886   - // 根据班次的吃饭时间添加吃饭班次
1887   - for (j = 0; j < aLpBc.length; j++) {
1888   - if (aLpBc[j].fnGetEatTime() > 0) {
1889   - aEatBc.push(_factory.createBcObj(
1890   - oLp,
1891   - "cf",
1892   - !aLpBc[j].isUp(), // 和上一个班次方向相反
1893   - 1,
1894   - _paramObj.addMinute(aLpBc[j].getArrTimeObj(), aLpBc[j].getStopTime()), // 使用上一个班次的到达时间作为开始时间
1895   - _paramObj
1896   - ));
1897   - }
1898   - }
1899   - aLpBc = aLpBc.concat(aEatBc);
1900   -
1901   - // 按照发车时间排序
1902   - aLpBc.sort(function(o1, o2) {
1903   - if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
1904   - return -1;
1905   - } else {
1906   - return 1;
1907   - }
1908   - });
1909   -
1910   - // 重新赋值fcno
1911   - for (j = 0; j < aLpBc.length; j++) {
1912   - aLpBc[j].fnSetFcno(j + 1);
1913   - }
1914   -
1915   - aAllBc = aAllBc.concat(aLpBc);
1916   - }
1917   -
1918   - var aGanttBc = [];
1919   - for (i = 0; i < aAllBc.length; i++) {
1920   - aGanttBc.push(aAllBc[i].toGanttBcObj());
1921   - }
1922   -
1923   - return aGanttBc;
1924   - }
1925   -
1926   - };
  1 +/**
  2 + * 内部行车计划对象。
  3 + * @constructor
  4 + */
  5 +var InternalScheduleObj = function(paramObj, lpArray, factory) {
  6 + // 参数对象
  7 + var _paramObj = paramObj;
  8 + // 外部的路牌数组
  9 + var _lpArray = lpArray;
  10 + // 工厂对象
  11 + var _factory = factory;
  12 +
  13 + //------------------ 初始化方法1,以及计算关联的内部变量 -----------------//
  14 + var _qIsUp; // 每一圈是上行开始还是下行开始
  15 + var _qCount = 0; // 总的圈数
  16 + var _internalLpArray = []; // 内部对象数组
  17 + var _aBxDesc = [ // 各种班型描述(班型名称,平均工时,平均需要的班次数,平均工时)
  18 + {'sType':'六工一休', 'fHoursV':6.66, 'fBcCount': 0, 'fAverTime': 0},
  19 + {'sType':'五工一休', 'fHoursV':6.85, 'fBcCount': 0, 'fAverTime': 0},
  20 + {'sType':'四工一休', 'fHoursV':7.14, 'fBcCount': 0, 'fAverTime': 0},
  21 + {'sType':'三工一休', 'fHoursV':7.61, 'fBcCount': 0, 'fAverTime': 0},
  22 + {'sType':'二工一休', 'fHoursV':8.57, 'fBcCount': 0, 'fAverTime': 0},
  23 + {'sType':'一工一休', 'fHoursV':11.42, 'fBcCount': 0, 'fAverTime': 0},
  24 + {'sType':'五工二休', 'fHoursV':7.99, 'fBcCount': 0, 'fAverTime': 0},
  25 + {'sType':'无工休', 'fHoursV':5.43, 'fBcCount': 0, 'fAverTime': 0}
  26 + ];
  27 +
  28 + var _fnInitFun1 = function() { // 初始化方法1
  29 + console.log("//---------------- 行车计划,初始化方法1 start ----------------//");
  30 +
  31 + //----------------------- 1、确定上标线的方向,圈的方向 -------------------//
  32 +
  33 + // 确定_qIsUp,哪个方向的首班车晚就用哪个
  34 + _qIsUp = _paramObj.getUpFirstDTimeObj().isBefore(
  35 + _paramObj.getDownFirstDTimeObj()) ? false : true;
  36 + // 上标线开始时间,就是方向的首班车时间
  37 + var st = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
  38 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  39 + var et;
  40 + var et_IsUp;
  41 + if (_paramObj.getUpLastDtimeObj().isBefore(
  42 + _paramObj.getDownLastDTimeObj())) {
  43 + et = _paramObj.getDownLastDTimeObj();
  44 + et_IsUp = false;
  45 + } else {
  46 + et = _paramObj.getUpLastDtimeObj();
  47 + et_IsUp = true;
  48 + }
  49 +
  50 + //------------------------ 2、计算总共有多少圈 ------------------------//
  51 +
  52 + // 以开始时间,结束时间,构造上标线用连班班次发车时间
  53 + var bcFcsjArrays = []; // 班次发车时间对象数组
  54 + var bcArsjArrays = []; // 班次到达时间对象数组
  55 + var isUp = _qIsUp; // 方向
  56 + var bcCount = 1; // 班次数
  57 +
  58 + var _kssj = st; // 开始时间
  59 + var _bcsj = paramObj.calcuTravelTime(_kssj, isUp); // 班次历时
  60 + var _arrsj = paramObj.addMinute(_kssj, _bcsj); // 到达时间
  61 + var _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj); // 停站时间
  62 +
  63 + do {
  64 + bcFcsjArrays.push(_kssj);
  65 + bcArsjArrays.push(_arrsj);
  66 +
  67 + _kssj = paramObj.addMinute(_kssj, _bcsj + _stoptime);
  68 + _bcsj = paramObj.calcuTravelTime(_kssj, isUp);
  69 + _arrsj = paramObj.addMinute(_kssj, _bcsj);
  70 + _stoptime = paramObj.fnCalcuFixedStopNumber(_arrsj, !isUp, _bcsj);
  71 +
  72 + bcCount ++;
  73 + isUp = !isUp;
  74 + } while(_kssj.isBefore(et));
  75 + bcCount--; // 因为先做do,所以总的班次要减1
  76 + //if (bcCount > 0 && bcArsjArrays[bcCount - 1].isAfter(et)) {
  77 + // // 如果最后一个班次的到达时间超过结束时间,也要去除
  78 + // bcFcsjArrays.splice(bcCount - 1, 1);
  79 + // bcArsjArrays.splice(bcCount - 1, 1);
  80 + // bcCount--;
  81 + //}
  82 + var _qCount_p1 = Math.floor(bcCount / 2); // 2个班次一圈
  83 + var _qCount_p2 = bcCount % 2; // 余下的1个班次也算一圈
  84 +
  85 + // 利用连班数组计算圈数
  86 + _qCount = 1; // 前面加1圈,补中标线的班次
  87 + _qCount += _qCount_p1;
  88 + _qCount += _qCount_p2;
  89 +
  90 + // 计算最后是不是还要补一圈
  91 + if (_qCount > 1) { // 总的圈数就1圈,没必要加了(其实是不可能的,除非参数里问题)
  92 + if (_qCount_p2 == 0) { // 没有余下班次,整数圈数
  93 + // 最后一个班次的方向一定和开始的方向相反,如:上-下,上-下,上-下,一共三圈,最后一个班次为下行
  94 + // 判定最后一个班次的方向和上标线判定结束时间的班次方向是否一致
  95 + if (!_qIsUp == et_IsUp) {
  96 + // 一致不用加圈数
  97 + } else {
  98 + // 不一致需要加圈补最后一个结束时间班次
  99 + _qCount ++;
  100 + }
  101 + } else {
  102 + // 有余下的圈数,最后要不补的班次不管上行,下行都在这一圈里
  103 + // 不需要在补圈数了
  104 + }
  105 + }
  106 +
  107 + //------------------------ 3、根据路牌数,圈数创建路牌对象 ----------------------//
  108 +
  109 + // 创建内部的路牌数组,并把之前的连班路牌添加进上标线路牌中
  110 + var i;
  111 + for (i = 0; i < _lpArray.length; i++) {
  112 + _internalLpArray.push(new InternalLpObj(_lpArray[i], _qCount, _qIsUp));
  113 + }
  114 + // 初始化上标线,从第1圈开始
  115 + _internalLpArray[0].initDataFromTimeToTime(bcFcsjArrays[0], et, _qIsUp, 1, _paramObj, _factory);
  116 +
  117 + // 以上标线为基础,计算各种班型工时对应的圈数、班次数
  118 + var aBcArray = _internalLpArray[0].getBcArray();
  119 + aBcArray[0].fnSetIsFirstBc(true); // 设置首班班次标识
  120 +
  121 + if (aBcArray.length % 2 != 0) { // 不能整除2,去除一个班次计算
  122 + aBcArray.splice(aBcArray.length - 1, 1);
  123 + }
  124 +
  125 + // 午饭吃饭时间
  126 + var iLTime = _paramObj.fnGetLunchTime();
  127 + // 晚饭吃饭时间
  128 + var iDTime = _paramObj.fnGetDinnerTime();
  129 + // 出场时间
  130 + var iOutTime = _qIsUp ? _paramObj.getUpOutTime() : _paramObj.getDownOutTime();
  131 + // 进场时间
  132 + var iInTime = _qIsUp ? _paramObj.getDownInTime() : _paramObj.getUpInTime();
  133 + // 例保时间
  134 + var iBTime = _paramObj.getLbTime();
  135 +
  136 + var sum = 0; // 总班次时间
  137 + for (i = 0; i < aBcArray.length; i++) {
  138 + sum += aBcArray[i].getBcTime() + aBcArray[i].getStopTime();
  139 + }
  140 + sum += iLTime; // 加午饭时间
  141 + sum += iDTime; // 加晚饭时间
  142 + for (i = 0; i < _aBxDesc.length; i++) {
  143 + _aBxDesc[i].fAverTime = sum / (aBcArray.length / 2); // 平均周转时间不算进出场,例保时间
  144 +
  145 + // 计算5休2的班次数(双进出场,4个例保)
  146 + if (i == 6) {
  147 + _aBxDesc[i].fQCount =
  148 + (_aBxDesc[i].fHoursV * 60 - iOutTime * 2 - iInTime * 2 - iBTime * 4) /
  149 + _aBxDesc[i].fAverTime;
  150 + _aBxDesc[i].fBcCount = _aBxDesc[i].fQCount * 2;
  151 + } else { // 进出场,2个例保
  152 + _aBxDesc[i].fQCount =
  153 + (_aBxDesc[i].fHoursV * 60 - iOutTime - iInTime - iBTime * 2) /
  154 + _aBxDesc[i].fAverTime;
  155 + _aBxDesc[i].fBcCount = _aBxDesc[i].fQCount * 2;
  156 + }
  157 + }
  158 +
  159 +
  160 + // 在第一个班次之前再添加一个模拟班次,用于中标线的作用
  161 + // 那一圈必定是低谷,而且圈索引0,班次索引1,暂时标记,最后删除
  162 + var iFirstStopTime =
  163 + _paramObj.fnCalcuFixedStopNumber(
  164 + _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -10),
  165 + _qIsUp
  166 + );
  167 + var iXXTime = _qIsUp ? _paramObj.getDownTroughTime() : _paramObj.getUpTroughTime();
  168 + var oFlagBc = _factory.createBcObj( // 标记班次
  169 + _internalLpArray[0],
  170 + "normal",
  171 + !_qIsUp,
  172 + 1,
  173 + _paramObj.addMinute(aBcArray[0].getFcTimeObj(), -(iFirstStopTime + iXXTime)),
  174 + _paramObj
  175 + );
  176 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  177 +
  178 + _internalLpArray[0].setBc(0, 1, oFlagBc);
  179 +
  180 + // 在最后一圈也补上一个或者2个模拟班次,暂时标记,最后需要删除
  181 + var aMaxBcIndex = _internalLpArray[0].getMaxBcObjPosition();
  182 + if (aMaxBcIndex[0] == _qCount - 1) { // 可能加半圈
  183 + oFlagBc = _factory.createBcObj( // 标记班次
  184 + _internalLpArray[0],
  185 + "normal",
  186 + !_qIsUp,
  187 + 1,
  188 + _paramObj.addMinute(
  189 + _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
  190 + _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
  191 + _paramObj
  192 + );
  193 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  194 + _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
  195 +
  196 + } else { // 加完整的一圈
  197 + oFlagBc = _factory.createBcObj( // 标记班次
  198 + _internalLpArray[0],
  199 + "normal",
  200 + _qIsUp,
  201 + 1,
  202 + _paramObj.addMinute(
  203 + _internalLpArray[0].getBc(_qCount - 2, 1).getArrTimeObj(),
  204 + _internalLpArray[0].getBc(_qCount - 2, 1).getStopTime()),
  205 + _paramObj
  206 + );
  207 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  208 + _internalLpArray[0].setBc(_qCount - 1, 0, oFlagBc);
  209 +
  210 + oFlagBc = _factory.createBcObj( // 标记班次
  211 + _internalLpArray[0],
  212 + "normal",
  213 + !_qIsUp,
  214 + 1,
  215 + _paramObj.addMinute(
  216 + _internalLpArray[0].getBc(_qCount - 1, 0).getArrTimeObj(),
  217 + _internalLpArray[0].getBc(_qCount - 1, 0).getStopTime()),
  218 + _paramObj
  219 + );
  220 + oFlagBc.fnSetDelFlag(true); // 标记了删除记号
  221 + _internalLpArray[0].setBc(_qCount - 1, 1, oFlagBc);
  222 +
  223 + }
  224 +
  225 + console.log("上行首班车时间:" + _paramObj.getUpFirstDTimeObj().format("HH:mm") +
  226 + "上行末班车时间:" + _paramObj.getUpLastDtimeObj().format("HH:mm"));
  227 + console.log("下行首班车时间:" + _paramObj.getDownFirstDTimeObj().format("HH:mm") +
  228 + "下行末班车时间:" + _paramObj.getDownLastDTimeObj().format("HH:mm"));
  229 + console.log("总共计算的圈数:" + _qCount);
  230 + console.log("圈的方向isUP:" + _qIsUp);
  231 + console.log("班型描述(以下):");
  232 + console.log(_aBxDesc);
  233 + console.log("所有路牌间隔描述(以下):");
  234 + for (i = 0; i < _internalLpArray.length; i++) {
  235 + console.log(_internalLpArray[i]._$_aVerticalIntervalTime);
  236 + }
  237 + console.log("//---------------- 行车计划,初始化方法1 end ----------------//");
  238 +
  239 + };
  240 +
  241 + //------------------ 初始化方法2,以及计算关联的内部变量 ----------------//
  242 + var _approximate_zgfQIndex; // 预估早高峰车辆从第几圈开始全部发出
  243 + var _approximate_zgfBIndex; // 预估早高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
  244 + var _approximate_wgfQIndex; // 预估晚高峰车辆从第几圈开始全部发出
  245 + var _approximate_wgfBIndex; // 预估晚高峰车辆从第几圈第几个班次开始全部发出(上行或下行)
  246 +
  247 + var _fnInitFun2 = function() { // 初始化方法2
  248 + console.log("//---------------- 行车计划,初始化方法2 start ----------------//");
  249 +
  250 + //------------------------ 1、计算车辆总数 ------------------------//
  251 + // 是用高峰上行周转时间除以高峰平均间隔得到的
  252 + // 这样算还算合理,车辆不多不少,待以后有新的算法再修正
  253 + var iClCount = _paramObj.calcuClzx();
  254 +
  255 + //------------------------ 2、计算所有路牌的发车在各个圈中的间隔 --------------------//
  256 + var i;
  257 + var j;
  258 + var iBindex = 1;
  259 + var iZzsj;
  260 + var oLp;
  261 + var iC1;
  262 + var iC2;
  263 +
  264 + for (i = 0; i < _qCount - 1; i++) {
  265 + while (iBindex <= 1) {
  266 + // 每圈每个方向的周转时间不一致,以上标线为主
  267 + oLp = _internalLpArray[0];
  268 + iZzsj = oLp.getBc(i + 1, iBindex).getFcTimeObj().diff(
  269 + oLp.getBc(i, iBindex).getFcTimeObj(), "m"
  270 + );
  271 +
  272 + iC1 = Math.floor(iZzsj / iClCount);
  273 + iC2 = iZzsj % iClCount;
  274 +
  275 + for (j = 0; j < iClCount - iC2; j++) {
  276 + oLp = _internalLpArray[j];
  277 + oLp.fnSetVerticalIntervalTime(i, iBindex, iC1);
  278 + }
  279 +
  280 + for (j = 0; j < iC2; j++) {
  281 + oLp = _internalLpArray[iClCount - iC2 + j];
  282 + oLp.fnSetVerticalIntervalTime(i, iBindex, iC1 + 1);
  283 + }
  284 +
  285 + iBindex ++;
  286 +
  287 + }
  288 + iBindex = 0;
  289 + }
  290 + // 最后一圈没有下一圈的参照,周转时间没发获取,由于都是低谷,所以使用倒数第二圈的间隔最为最后一圈的间隔
  291 + for (i = 0; i < _internalLpArray.length; i++) {
  292 + oLp = _internalLpArray[i];
  293 + oLp.fnSetVerticalIntervalTime(_qCount - 1, 0, oLp.fnGetVerticalIntervalTime(_qCount - 2, 0));
  294 + oLp.fnSetVerticalIntervalTime(_qCount - 1, 1, oLp.fnGetVerticalIntervalTime(_qCount - 2, 1));
  295 + }
  296 +
  297 + //------------------------ 3、预估早高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
  298 +
  299 + // 以上标线为标准,查找离早高峰开始时间最近的班次作为早高峰开始班次
  300 + // 以这个班次为早高峰起点,全部出车策略
  301 + var qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
  302 + _paramObj.getMPeakStartTimeObj(), true, true);
  303 + var qIndex = qbcIndexArray[0]; // 第几圈
  304 + var bIndex = qbcIndexArray[1]; // 第几个班次
  305 +
  306 + for (i = 1; i < _internalLpArray.length; i++) {
  307 + _fnGenerateBcAndSetBc(i, qIndex, bIndex);
  308 + }
  309 +
  310 + _approximate_zgfQIndex = qIndex;
  311 + _approximate_zgfBIndex = bIndex;
  312 +
  313 + //------------------------ 4、预估晚高峰全部出车第几圈第几个班次全部出车,计算路牌之间的发车间隔 ------------------//
  314 +
  315 + // 以上标线为标准,查找离晚高峰开始时间最近的班次作为晚高峰开始班次
  316 + // 以这个班次为早高峰起点,全部出车策略
  317 + qbcIndexArray = _internalLpArray[0].getQBcIndexWithFcTime(
  318 + _paramObj.getEPeakStartTimeObj(), true, true);
  319 + qIndex = qbcIndexArray[0]; // 第几圈
  320 + bIndex = qbcIndexArray[1]; // 第几个班次
  321 +
  322 + for (i = 1; i < _internalLpArray.length; i++) {
  323 + _fnGenerateBcAndSetBc(i, qIndex, bIndex);
  324 + }
  325 +
  326 + _approximate_wgfQIndex = qIndex;
  327 + _approximate_wgfBIndex = bIndex;
  328 +
  329 + console.log("早高峰周转时间(固定最大停战时间):" + _paramObj.calcuPeakZzsj() + "分钟");
  330 + console.log("早高峰发车时间范围:" + _paramObj.getMPeakMinFcjx() + "分钟 --- " + _paramObj.getMPeakMaxFcjx() + "分钟");
  331 + console.log("预估早高峰第" + _approximate_zgfQIndex + "(index)圈,第" + _approximate_zgfBIndex + "(index)班次车辆全部发出");
  332 + console.log("预估晚高峰第" + _approximate_wgfQIndex + "(index)圈,第" + _approximate_wgfBIndex + "(index)班次车辆全部发出");
  333 + console.log("//---------------- 行车计划,初始化方法2 end ----------------//");
  334 + };
  335 +
  336 + //----------------------- 初始化方法3,计算连班分班的路牌分布 ----------------//
  337 + var _iBx_lb_lpcount; // 连班路牌数
  338 + var _iBx_5_2_fb_lpcount; // 5休2分班路牌数
  339 + var _iBx_other_fb_lpcount; // 其他分班路牌数
  340 +
  341 + var _fnInitFun3 = function() { // 初始化方法3
  342 + console.log("//---------------- 行车计划,初始化方法3 start ----------------//");
  343 +
  344 + //--------------------- 1、计算分班连班班型车辆分布数 --------------------//
  345 + // 总共车辆数(高峰最大车辆数)
  346 + var iCls = _paramObj.calcuClzx();
  347 + // 低谷最少配车(连班车数量)
  348 + var iDgminpc = Math.round(_paramObj.calcuTroughZzsj() / _paramObj.getTroughMaxFcjx());
  349 + // 加班车路牌数(做5休2的路牌数)
  350 + var i_5_2_lpes = _paramObj.getJBLpes();
  351 +
  352 + // 做些简单的验证
  353 + if (iCls < iDgminpc) {
  354 + alert("总配车数小于低谷最小配车");
  355 + throw "总配车数小于低谷最小配车";
  356 + }
  357 + if (iDgminpc < 2) {
  358 + alert("连班路牌小于2,办不到啊");
  359 + throw "连班路牌小于2,办不到啊";
  360 + }
  361 + if (iCls - iDgminpc < i_5_2_lpes) {
  362 + alert("总分班路牌数小于加班路牌数");
  363 + throw "总分班路牌数小于加班路牌数";
  364 + }
  365 +
  366 + //// 修正连班路牌数,班次间隔大于20的,加1,直至班次间隔小于20
  367 + //while(_paramObj.calcuPeakZzsj() / iDgminpc > 20) {
  368 + // iDgminpc ++;
  369 + //}
  370 + _iBx_lb_lpcount = iDgminpc;
  371 +
  372 + _iBx_5_2_fb_lpcount = i_5_2_lpes;
  373 + _iBx_other_fb_lpcount = iCls - _iBx_lb_lpcount - i_5_2_lpes;
  374 +
  375 + //------------------------ 2、利用间隔法计算连班路牌分布 --------------------//
  376 + var i;
  377 + var j;
  378 + var iC1 = Math.floor(_internalLpArray.length / _iBx_lb_lpcount);
  379 + var iC2 = _internalLpArray.length % _iBx_lb_lpcount;
  380 + var iLpIndex;
  381 +
  382 + for (i = 0; i < _iBx_lb_lpcount - iC2; i++) {
  383 + iLpIndex = i * iC1;
  384 + _internalLpArray[iLpIndex].setBxLb(true);
  385 + _internalLpArray[iLpIndex].setBxDesc("连班");
  386 + }
  387 + for (j = 0; j < iC2; j++) {
  388 + iLpIndex = i * iC1 + j * (iC1 + 1);
  389 + _internalLpArray[iLpIndex].setBxLb(true);
  390 + _internalLpArray[iLpIndex].setBxDesc("连班");
  391 + }
  392 +
  393 + //------------------------ 3、利用间隔法计算分班班型路牌分布 --------------------//
  394 + // 获取分班路牌索引
  395 + var aNotLbIndexes = [];
  396 + for (i = 0; i < _internalLpArray.length; i++) {
  397 + if (!_internalLpArray[i].isBxLb()) {
  398 + aNotLbIndexes.push(i);
  399 + }
  400 + }
  401 + // 先5休2分班
  402 + iC1 = Math.floor(aNotLbIndexes.length / _iBx_5_2_fb_lpcount);
  403 + iC2 = aNotLbIndexes.length % _iBx_5_2_fb_lpcount;
  404 +
  405 + for (i = 0; i < _iBx_5_2_fb_lpcount - iC2; i++) {
  406 + iLpIndex = aNotLbIndexes[i * iC1];
  407 + _internalLpArray[iLpIndex].setBxLb(false);
  408 + _internalLpArray[iLpIndex].setBxFb(true);
  409 + _internalLpArray[iLpIndex].setBxFb5_2(true);
  410 + _internalLpArray[iLpIndex].setBxDesc("5休2分班");
  411 + }
  412 + for (i = 0; i < iC2; i++) {
  413 + iLpIndex = aNotLbIndexes[_iBx_5_2_fb_lpcount - iC2 + i * (iC1 + 1)];
  414 + _internalLpArray[iLpIndex].setBxLb(false);
  415 + _internalLpArray[iLpIndex].setBxFb(true);
  416 + _internalLpArray[iLpIndex].setBxFb5_2(true);
  417 + _internalLpArray[iLpIndex].setBxDesc("5休2分班");
  418 + }
  419 + // 其他分班
  420 + for (i = 0; i < aNotLbIndexes.length; i++) {
  421 + iLpIndex = aNotLbIndexes[i];
  422 + if (!_internalLpArray[iLpIndex].isBxFb5_2()) {
  423 + _internalLpArray[iLpIndex].setBxLb(false);
  424 + _internalLpArray[iLpIndex].setBxFb(true);
  425 + _internalLpArray[iLpIndex].setBxFb5_2(false);
  426 + _internalLpArray[iLpIndex].setBxDesc("其他分班");
  427 + }
  428 + }
  429 +
  430 + console.log("高峰周转时间:" + _paramObj.calcuPeakZzsj());
  431 + console.log("连班路牌数:" + _iBx_lb_lpcount);
  432 + console.log("5休2分班路牌数:" + _iBx_5_2_fb_lpcount);
  433 + console.log("其他分班路牌数:" + _iBx_other_fb_lpcount);
  434 + var aLbIndexes = [];
  435 + for (i = 0; i < _internalLpArray.length; i++) {
  436 + if (_internalLpArray[i].isBxLb()) {
  437 + aLbIndexes.push(i);
  438 + }
  439 + }
  440 + console.log("连班路牌indexes=" + aLbIndexes);
  441 + var a_5_2_fbIndexes = [];
  442 + for (i = 0; i < _internalLpArray.length; i++) {
  443 + if (_internalLpArray[i].isBxFb() && _internalLpArray[i].isBxFb5_2()) {
  444 + a_5_2_fbIndexes.push(i);
  445 + }
  446 + }
  447 + console.log("5休2分班路牌indexes=" + a_5_2_fbIndexes);
  448 + var a_other_fbIndexes = [];
  449 + for (i = 0; i < _internalLpArray.length; i++) {
  450 + if (_internalLpArray[i].isBxFb() && !_internalLpArray[i].isBxFb5_2()) {
  451 + a_other_fbIndexes.push(i);
  452 + }
  453 + }
  454 + console.log("其他分班路牌indexes=" + a_other_fbIndexes);
  455 +
  456 + console.log("//---------------- 行车计划,初始化方法3 end ----------------//");
  457 + };
  458 +
  459 + //----------------------- 初始化方法4,计算中标线位置 -------------------------//
  460 + var _iZbx_lpIndex; // 中标线对应第几个路牌
  461 +
  462 + var _fnInitFun4 = function() { // 初始化方法4
  463 + console.log("//---------------- 行车计划,初始化方法4 start ----------------//");
  464 +
  465 + //---------------------------- 1、模拟一个中标线,使用临时路牌 ----------------------//
  466 + // 构造中标线
  467 + // 中标线开始时间,就是方向的首班车时间
  468 + var oSt = !_qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
  469 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  470 + // 上标线结束时间,使用最晚的末班车时间,结束时间的班次方向
  471 + var oEt;
  472 + if (_paramObj.getUpLastDtimeObj().isBefore(
  473 + _paramObj.getDownLastDTimeObj())) {
  474 + oEt = _paramObj.getDownLastDTimeObj();
  475 + } else {
  476 + oEt = _paramObj.getUpLastDtimeObj();
  477 + }
  478 +
  479 + var oTempLp = new InternalLpObj({lpNo: -999, lpName: "-999"}, _qCount, _qIsUp);
  480 + oTempLp.initDataFromTimeToTime(
  481 + oSt,
  482 + oEt,
  483 + !_qIsUp,
  484 + 0,
  485 + _paramObj,
  486 + _factory
  487 + );
  488 +
  489 + //------------------------ 2、找出中标线的早高峰班次,计算应该插在当前路牌数组的那个位置 ----------------//
  490 + // 找出中标线对应的早高峰的班次对象
  491 + var oZb_gf_bc = oTempLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
  492 + //alert(oZb_gf_bc.getFcTimeObj().format("HH:mm"));
  493 +
  494 + // 把所有连班路牌高峰班次重新构造成一个一个的圈数组,计算对应中标线最近的是第几个路牌
  495 + // 中标线和上标线一样在连班路牌上
  496 + var aTempq = [];
  497 + var oTempq;
  498 + var oTempb;
  499 + var i;
  500 + var oLp;
  501 +
  502 + var aLbIndexes = []; // 连班的路牌索引
  503 + for (i = 0; i < _internalLpArray.length; i++) {
  504 + if (_internalLpArray[i].isBxLb()) {
  505 + aLbIndexes.push(i);
  506 + }
  507 + }
  508 +
  509 + for (i = 0; i < aLbIndexes.length; i++) {
  510 + oLp = _internalLpArray[aLbIndexes[i]];
  511 +
  512 + oTempb = oLp.getBc(_approximate_zgfQIndex, _approximate_zgfBIndex);
  513 + if (oTempb.isUp() == _qIsUp) {
  514 + oTempq = new InternalGroupObj(oLp, _qIsUp, oTempb, undefined);
  515 + } else {
  516 + oTempq = new InternalGroupObj(oLp, _qIsUp, undefined, oTempb);
  517 + }
  518 + aTempq.push(oTempq);
  519 +
  520 + }
  521 +
  522 + var aTtindex = oTempLp.fnGetQBcIndexWithFcTimeFromGroupArray( // 找出最接近中标线的路牌索引
  523 + oZb_gf_bc.getFcTimeObj(),
  524 + aTempq,
  525 + true,
  526 + true
  527 + );
  528 +
  529 + _iZbx_lpIndex = aLbIndexes[aTtindex[0]]; // 中标线放在第几个路牌
  530 +
  531 + oTempLp.getMinBcObj().fnSetIsFirstBc(true); // 设置首班班次标识
  532 +
  533 + if (_iZbx_lpIndex == 0) { // 如果中标线和上标线一致
  534 + var oFirstBcIndexes = oTempLp.getMinBcObjPosition();
  535 + var oFirstBc = oTempLp.getMinBcObj();
  536 + oFirstBc.setLp(_internalLpArray[_iZbx_lpIndex]);
  537 + oFirstBc.fnSetDelFlag(false);
  538 + _internalLpArray[_iZbx_lpIndex].setBc(oFirstBcIndexes[0], oFirstBcIndexes[1], oFirstBc);
  539 + } else {
  540 + oTempLp.setLp(_lpArray[_iZbx_lpIndex]); // 设置原始路牌对象
  541 + oTempLp._$_aVerticalIntervalTime = _internalLpArray[_iZbx_lpIndex]._$_aVerticalIntervalTime; // 设置纵向最小发车间隔
  542 + oTempLp.setBxLb(_internalLpArray[_iZbx_lpIndex].isBxLb());
  543 + oTempLp.setBxFb(_internalLpArray[_iZbx_lpIndex].isBxFb());
  544 + oTempLp.setBxFb5_2(_internalLpArray[_iZbx_lpIndex].isBxFb5_2());
  545 +
  546 + // 修正除了第一个班次外,其余其他班次
  547 + var iBcindex = 0;
  548 + for (i = 1; i < _qCount; i++) {
  549 + while (iBcindex <= 1) {
  550 + if (oTempLp.getBc(i, iBcindex)) { // 替换存在的班次
  551 + oTempLp.setBc(i, iBcindex, _fnGenerateBc(_iZbx_lpIndex, i, iBcindex));
  552 + }
  553 + iBcindex ++;
  554 + }
  555 + iBcindex = 0;
  556 + }
  557 +
  558 + _internalLpArray[_iZbx_lpIndex] = oTempLp;
  559 + }
  560 +
  561 + console.log("中标线对应第" + (_iZbx_lpIndex + 1) + "个路牌");
  562 +
  563 + console.log("//---------------- 行车计划,初始化方法4 end ----------------//");
  564 + };
  565 +
  566 + //-------------------- 重要的内部方法 -----------------------//
  567 + /**
  568 + * 核心方法,利用路牌间隔纵向生成班次。
  569 + * @param iLpindex 路牌索引
  570 + * @param iQindex 圈索引
  571 + * @param iBcindex 班次索引
  572 + * @returns object InternalBcObj,失败 false
  573 + */
  574 + var _fnGenerateBc = function(iLpindex, iQindex, iBcindex) {
  575 + // 以上标线为起始点,使用路牌在不同圈,班次索引的发车间隔,计算班次
  576 + // 注意,发车间隔是指下一个班次应该距离当前班次间隔,是从下往上的
  577 +
  578 + // 1、参数验证
  579 + if (iLpindex == 0) { // 上标线的班次不需要生成
  580 + return false;
  581 + }
  582 +
  583 + // 2、计算间隔
  584 + var i;
  585 + var oLp;
  586 + var iTime = 0;
  587 + for (i = 0; i < iLpindex; i++) {
  588 + oLp = _internalLpArray[i];
  589 + iTime += oLp.fnGetVerticalIntervalTime(iQindex, iBcindex);
  590 + }
  591 +
  592 + // 3、生成班次
  593 + var _oKsbc = _internalLpArray[0].getBc(iQindex, iBcindex);
  594 + if (!_oKsbc) {
  595 + return false;
  596 + }
  597 + var _oKssj = _paramObj.addMinute(_oKsbc.getFcTimeObj(), iTime);
  598 + var _oBc = _factory.createBcObj(
  599 + _internalLpArray[iLpindex],
  600 + "normal", _oKsbc.isUp(),
  601 + 1, _oKssj, _paramObj);
  602 +
  603 + return _oBc;
  604 +
  605 + };
  606 +
  607 + /**
  608 + * 核心方法,在指定位置生成班次并添加到路牌指定位置中。
  609 + * @param lpIndex 第几个路牌
  610 + * @param qIndex 第几圈
  611 + * @param bcIndex 第几个班次
  612 + */
  613 + var _fnGenerateBcAndSetBc = function(lpIndex, qIndex, bcIndex) {
  614 + var _bcObj = _fnGenerateBc(lpIndex, qIndex, bcIndex);
  615 + if (_bcObj) {
  616 + _internalLpArray[lpIndex].setBc(qIndex, bcIndex, _bcObj);
  617 + }
  618 + };
  619 +
  620 + /**
  621 + * 获取班次列表。
  622 + * @param oIsUp 是否上行
  623 + * @param oStartTime 开始时间对象
  624 + * @returns [(InternalBcObj)]
  625 + */
  626 + var _fnGetBcList2 = function(oIsUp, oStartTime) {
  627 + var i;
  628 + var j;
  629 + var oLp;
  630 + var oBc;
  631 + var aBc = [];
  632 +
  633 + for (j = 0; j < _qCount; j++) {
  634 + for (i = 0; i < _internalLpArray.length; i++) {
  635 + oLp = _internalLpArray[i];
  636 + oBc = oLp.getBc(
  637 + j,
  638 + _qIsUp == oIsUp ? 0 : 1
  639 + );
  640 + if (oBc && oBc.getFcTimeObj().isAfter(oStartTime)) {
  641 + aBc.push(oBc);
  642 + }
  643 + }
  644 + }
  645 +
  646 + var aBcFcTime = [];
  647 + for (i = 0; i < aBc.length; i++) {
  648 + oBc = aBc[i];
  649 + aBcFcTime.push(oBc.getFcTimeObj().format("HH:mm"));
  650 + }
  651 + console.log((oIsUp ? "上行班次列表:" : "下行班次列表:") + aBcFcTime.join(","));
  652 +
  653 + return aBc;
  654 + };
  655 +
  656 + /**
  657 + * 获取班次列表。
  658 + * @param isUp boolean 是否上行
  659 + * @returns [(InternalBcObj)]
  660 + */
  661 + var _fnGetBcList = function(isUp) {
  662 + var i;
  663 + var j;
  664 + var oLp;
  665 + var oBc;
  666 + var aBc = [];
  667 +
  668 + for (j = 0; j < _qCount; j++) {
  669 + for (i = 0; i < _internalLpArray.length; i++) {
  670 + oLp = _internalLpArray[i];
  671 + oBc = oLp.getBc(
  672 + j,
  673 + _qIsUp == isUp ? 0 : 1
  674 + );
  675 + if (oBc) {
  676 + aBc.push(oBc);
  677 + }
  678 + }
  679 + }
  680 +
  681 + var aBcFcTime = [];
  682 + for (i = 0; i < aBc.length; i++) {
  683 + oBc = aBc[i];
  684 + aBcFcTime.push(oBc.getFcTimeObj().format("HH:mm"));
  685 + }
  686 + console.log((isUp ? "上行班次列表:" : "下行班次列表:") + aBcFcTime.join(","));
  687 +
  688 + return aBc;
  689 + };
  690 +
  691 + /**
  692 + * 查找离指定时间最近的前面的班次索引信息
  693 + * @param timeObj 查找时间
  694 + * @param isUp 是否上行
  695 + * @returns [{路牌index},{圈index},{班次index}]
  696 + */
  697 + var _fnFindUpClosedBcIndexWithTime = function(timeObj, isUp) {
  698 +
  699 + var _lpObj;
  700 + var _groupObj;
  701 + var _bcObj;
  702 + var _i;
  703 + var _j;
  704 + var timediff; // 时间差取绝对值
  705 +
  706 + var _lpIndex;
  707 + var _up_qIndex;
  708 + var _up_bIndex;
  709 +
  710 + for (_i = 0; _i < _qCount; _i++) {
  711 + for (_j = 0; _j < _internalLpArray.length; _j++) {
  712 + _lpObj = _internalLpArray[_j];
  713 + _groupObj = _lpObj.getGroup(_i);
  714 + _bcObj = isUp == _qIsUp ? _groupObj.getBc1() : _groupObj.getBc2();
  715 + if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
  716 + _bcObj = _fnGenerateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
  717 + }
  718 + if (_bcObj) {
  719 + if (timeObj.diff(_bcObj.getFcTimeObj()) >= 0) {
  720 + if (!timediff) {
  721 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  722 + _lpIndex = _j;
  723 + _up_qIndex = _i;
  724 + _up_bIndex = isUp == _qIsUp ? 0 : 1;
  725 + } else {
  726 + if (timeObj.diff(_bcObj.getFcTimeObj()) < timediff) {
  727 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  728 + _lpIndex = _j;
  729 + _up_qIndex = _i;
  730 + _up_bIndex = isUp == _qIsUp ? 0 : 1;
  731 + }
  732 + }
  733 + }
  734 + }
  735 + }
  736 + }
  737 +
  738 + if (_lpIndex == undefined) {
  739 + return false;
  740 + }
  741 +
  742 + var bcindex = [];
  743 + bcindex.push(_lpIndex);
  744 + bcindex.push(_up_qIndex);
  745 + bcindex.push(_up_bIndex);
  746 +
  747 + return bcindex;
  748 + };
  749 +
  750 + /**
  751 + * 查找离指定时间最近的后面的班次索引信息
  752 + * @param timeObj 查找时间
  753 + * @param isUp 是否上行
  754 + * @returns [{路牌index},{圈index},{班次index}]
  755 + */
  756 + var _fnFindDownClosedBcIndexWithTime = function(timeObj, isUp) {
  757 + var _lpObj;
  758 + var _groupObj;
  759 + var _bcObj;
  760 + var _i;
  761 + var _j;
  762 + var timediff; // 时间差取绝对值
  763 +
  764 + var _lpIndex;
  765 + var _down_qIndex;
  766 + var _down_bIndex;
  767 +
  768 + var flag;
  769 +
  770 + for (_i = 0; _i < _qCount; _i++) {
  771 + for (_j = 0; _j < _internalLpArray.length; _j++) {
  772 + _lpObj = _internalLpArray[_j];
  773 + _groupObj = _lpObj.getGroup(_i);
  774 + // TODO:bug
  775 + _bcObj = isUp == _qIsUp ? _groupObj.getBc1() : _groupObj.getBc2();
  776 + if (!_bcObj) { // 没有班次动态生成一个,可能生成不出的
  777 + _bcObj = _fnGenerateBc(_j, _i, isUp == _qIsUp ? 0 : 1);
  778 + }
  779 + if (_bcObj) {
  780 + //console.log("timeobj -> bcobj diff flag " +
  781 + // timeObj.format("HH:mm") + "->" +
  782 + // _bcObj.getFcTimeObj().format("HH:mm") +
  783 + // timeObj.diff(_bcObj.getFcTimeObj()) +
  784 + // (timeObj.diff(_bcObj.getFcTimeObj()) <= 0)
  785 + //);
  786 +
  787 + flag = (timeObj.diff(_bcObj.getFcTimeObj())) <= 0;
  788 +
  789 + if (flag) {
  790 + if (!timediff) {
  791 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  792 + _lpIndex = _j;
  793 + _down_qIndex = _i;
  794 + _down_bIndex = isUp == _qIsUp ? 0 : 1;
  795 + } else {
  796 + if ((timeObj.diff(_bcObj.getFcTimeObj())) > timediff) {
  797 + timediff = timeObj.diff(_bcObj.getFcTimeObj());
  798 + _lpIndex = _j;
  799 + _down_qIndex = _i;
  800 + _down_bIndex = isUp == _qIsUp ? 0 : 1;
  801 + }
  802 + }
  803 + }
  804 + }
  805 + }
  806 + }
  807 +
  808 + if (_lpIndex == undefined) {
  809 + return false;
  810 + }
  811 +
  812 + var bcindex = [];
  813 + bcindex.push(_lpIndex);
  814 + bcindex.push(_down_qIndex);
  815 + bcindex.push(_down_bIndex);
  816 +
  817 + return bcindex;
  818 + };
  819 +
  820 + /**
  821 + * 获取班次索引。
  822 + * @param oBc 班次对象
  823 + * @returns [{路牌索引},{圈索引},{班次索引}]
  824 + */
  825 + var _fnGetBcIndex = function(oBc) {
  826 + // 路牌索引
  827 + var i;
  828 + var iLpIndex;
  829 + for (i = 0; i < _internalLpArray.length; i++) {
  830 + if (_internalLpArray[i]._$$_orign_lp_obj == oBc._$$_internal_lp_obj._$$_orign_lp_obj) {
  831 + iLpIndex = i;
  832 + break;
  833 + }
  834 + }
  835 + // 圈索引
  836 + var j;
  837 + var iGroupIndex;
  838 + var bFlag = false;
  839 + for (i = 0; i < _internalLpArray.length; i++) {
  840 + if (bFlag) {
  841 + break;
  842 + }
  843 + for (j = 0; j < _qCount; j++) {
  844 + if (_internalLpArray[i]._$_groupBcArray[j] == oBc._$$_internal_group_obj) {
  845 + iGroupIndex = j;
  846 + bFlag = true;
  847 + break;
  848 + }
  849 + }
  850 + }
  851 + // 班次索引
  852 + var iBcIndex = _qIsUp == oBc.isUp() ? 0 : 1;
  853 +
  854 + if (iLpIndex == undefined) {
  855 + return null;
  856 + } else {
  857 + return [].concat(iLpIndex, iGroupIndex, iBcIndex);
  858 + }
  859 +
  860 + };
  861 +
  862 + return {
  863 + //------------- 布局初始化方法 ------------//
  864 + /**
  865 + * 初始化数据,使用标线初始化
  866 + */
  867 + fnInitDataWithBxLayout: function() {
  868 + // 初始化布局1,构造上标线,计算圈数,把上标线数据放入第一个路牌中
  869 + _fnInitFun1();
  870 + // 初始化布局2,从上标线的某个班次开始,构造所有路牌的早高峰班次,晚高峰班次,计算路牌在各个圈中的间隔
  871 + _fnInitFun2();
  872 + // 初始化布局3,计算连班分班路牌分布
  873 + _fnInitFun3();
  874 + // 初始化布局4,计算中标线位置
  875 + _fnInitFun4();
  876 +
  877 + },
  878 +
  879 + /**
  880 + * 调整高峰班次,
  881 + * 初始化生成早高峰,晚高峰班次并不准确,因为根据高峰时间段,并不在一个完整圈内,应该是在两个或多个圈之间
  882 + * 当初始化定好布局后(上标线,中标线),然后确定每个路牌的班型(连班,分班,5休2分班)后
  883 + * 然后重新计算框在高峰时间段内的班次索引,不足的添加,之前多加的删除(只删除分班路牌上的)
  884 + * @param isZgf 是否早高峰
  885 + * @param isUp 是否上行
  886 + */
  887 + fnAdjustGfbc : function(isZgf, isUp) {
  888 + var oStartTime; // 开始时间
  889 + var oEndTime; // 结束时间
  890 + var aStartBcIndex; // 开始班次索引
  891 + var aEndBcIndex; // 结束班次索引
  892 +
  893 + oStartTime = isZgf ? _paramObj.getMPeakStartTimeObj() : _paramObj.getEPeakStartTimeObj();
  894 + oEndTime = isZgf ? _paramObj.getMPeakEndTimeObj() : _paramObj.getEPeakEndTimeObj();
  895 +
  896 + aStartBcIndex = _fnFindUpClosedBcIndexWithTime(oStartTime, isUp);
  897 + aEndBcIndex = _fnFindDownClosedBcIndexWithTime(oEndTime, isUp);
  898 +
  899 + var iLpIndex;
  900 + var iQIndex;
  901 + var iBcIndex;
  902 + var iQInternelCount; // 高峰时间段中间包含的圈数
  903 + var i;
  904 + var j;
  905 +
  906 + var oLp;
  907 +
  908 + if (aStartBcIndex && aEndBcIndex) {
  909 + iLpIndex = aStartBcIndex[0];
  910 + iQIndex = aStartBcIndex[1];
  911 + iBcIndex = aStartBcIndex[2];
  912 +
  913 + // 处理头
  914 + // 删除头部多余班次
  915 + for (j = 0; j < iLpIndex; j++) {
  916 + oLp = _internalLpArray[j];
  917 + if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
  918 + oLp.removeBc(iQIndex, iBcIndex);
  919 + }
  920 + }
  921 +
  922 + for (j = iLpIndex; j < _internalLpArray.length; j++) {
  923 + oLp = _internalLpArray[j];
  924 + if (!oLp.getBc(iQIndex, iBcIndex)) {
  925 + _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
  926 + }
  927 + }
  928 +
  929 + // 处理中间
  930 + iQInternelCount = aEndBcIndex[1] - aStartBcIndex[1] - 1;
  931 + for (i = 1; i <= iQInternelCount; i++) {
  932 + oLp = _internalLpArray[iQIndex + i];
  933 +
  934 + if (!oLp.getBc(iQIndex + i, iBcIndex)) {
  935 + _fnGenerateBcAndSetBc(i, iQIndex + i, iBcIndex);
  936 + }
  937 + }
  938 +
  939 + // 处理尾部
  940 + iLpIndex = aEndBcIndex[0];
  941 + iQIndex = aEndBcIndex[1];
  942 + iBcIndex = aEndBcIndex[2];
  943 +
  944 + // 删除尾部多余的班次
  945 + for (j = iLpIndex; j < _internalLpArray.length; j++) {
  946 + oLp = _internalLpArray[j];
  947 + if (oLp.isBxFb() && oLp.getBc(iQIndex, iBcIndex)) {
  948 + oLp.removeBc(iQIndex, iBcIndex);
  949 + }
  950 + }
  951 +
  952 + if (aStartBcIndex[1] != aEndBcIndex[1]) { // 指定时间范围跨圈
  953 + for (j = 0; j < iLpIndex; j++) {
  954 + oLp = _internalLpArray[j];
  955 + if (!oLp.getBc(iQIndex, iBcIndex)) {
  956 + _fnGenerateBcAndSetBc(j, iQIndex, iBcIndex);
  957 + }
  958 + }
  959 + } else {
  960 + // 不跨圈,不用处理,处理头的时候已经加了
  961 + }
  962 +
  963 + }
  964 +
  965 + },
  966 +
  967 + /**
  968 + * 按照营运时间要求补充班次,
  969 + * 早高峰7:45分以前出场运营,
  970 + * 晚高峰16:10分以前出场运营
  971 + */
  972 + fnCalcuLpBc_yy: function() {
  973 + // 补班次的时候,针对的是分班班型
  974 + var i;
  975 + var _oLp;
  976 + var _oBc;
  977 + var _aMinBcIndex;
  978 + var _aMaxBcIndex;
  979 +
  980 + var _qIndex;
  981 + var _bIndex;
  982 +
  983 + var _zgfCDate = _paramObj.toTimeObj("7:45");
  984 + var _wgfCDate = _paramObj.toTimeObj("16:10");
  985 + var _ccsj;
  986 +
  987 + for (i = 0; i < _internalLpArray.length; i++) {
  988 + _oLp = _internalLpArray[i];
  989 + if (_oLp.isBxFb()) { // 分班路牌
  990 + // 早高峰部分
  991 + _aMinBcIndex = _oLp.getMinBcObjPosition();
  992 + _qIndex = _aMinBcIndex[0];
  993 + _bIndex = _aMinBcIndex[1];
  994 + _oBc = _oLp.getBc(_qIndex, _bIndex);
  995 + if (_qIsUp) {
  996 + _ccsj = _bIndex == 0 ?
  997 + _paramObj.getUpOutTime() :
  998 + _paramObj.getDownOutTime();
  999 + } else {
  1000 + _ccsj = _bIndex == 0 ?
  1001 + _paramObj.getDownOutTime() :
  1002 + _paramObj.getUpOutTime();
  1003 + }
  1004 + if (_zgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
  1005 + _fnGenerateBcAndSetBc(
  1006 + i,
  1007 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  1008 + _bIndex == 0 ? 1 : 0
  1009 + )
  1010 + }
  1011 +
  1012 + // 晚高峰部分
  1013 + _aMaxBcIndex = _oLp.getMaxBcObjPosition();
  1014 + _qIndex = _aMaxBcIndex[0];
  1015 + _bIndex = _aMaxBcIndex[1];
  1016 + _oBc = _oLp.getBc(
  1017 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  1018 + _bIndex == 0 ? 1 : 0
  1019 + );
  1020 + if (!_oBc) { // 前一个班次不存在,再判定加不加
  1021 + _oBc = _oLp.getBc(_qIndex, _bIndex);
  1022 + if (_qIsUp) {
  1023 + _ccsj = _bIndex == 0 ?
  1024 + _paramObj.getUpOutTime() :
  1025 + _paramObj.getDownOutTime();
  1026 + } else {
  1027 + _ccsj = _bIndex == 0 ?
  1028 + _paramObj.getDownOutTime() :
  1029 + _paramObj.getUpOutTime();
  1030 + }
  1031 + if (_wgfCDate.isBefore(_paramObj.addMinute(_oBc.getFcTimeObj(), -_ccsj))) {
  1032 + _fnGenerateBcAndSetBc(
  1033 + i,
  1034 + _bIndex == 0 ? _qIndex - 1 : _qIndex,
  1035 + _bIndex == 0 ? 1 : 0
  1036 + )
  1037 + }
  1038 + }
  1039 + }
  1040 + }
  1041 + },
  1042 +
  1043 + /**
  1044 + * 补充做5休2的班型班次。
  1045 + * 1、确认5_2班型大致多少圈(小数点过.7进位)
  1046 + * 2、获取当前5_2两端车次链的信息,每段的班次数目,还差几个班次没加
  1047 + * 3、如果前面的车次链班次少,则从前面的车次链开始加
  1048 + * 4、如果车次链班次数一样,从从后面的车次链开始加
  1049 + * 5、加班次时都是往车次链前方加
  1050 + * 6、如果前面车次链不能再加班次了,从后面车次链加
  1051 + */
  1052 + fnCalcuLpBx_5_2: function() {
  1053 + // 计算做5休2班型所需的班次数
  1054 + var iBxBcount = _aBxDesc[6].fBcCount;
  1055 + if (iBxBcount - Math.floor(iBxBcount) > 0.7) {
  1056 + iBxBcount = Math.floor(iBxBcount) + 1;
  1057 + } else {
  1058 + iBxBcount = Math.floor(iBxBcount);
  1059 + }
  1060 +
  1061 + var i;
  1062 + var j;
  1063 + var oLp;
  1064 + var iAddBcCount;
  1065 + var oBcChain1;
  1066 + var oBcChain2;
  1067 + var iQindex;
  1068 + var iBindex;
  1069 +
  1070 + for (i = 0; i < _internalLpArray.length; i++) {
  1071 + oLp = _internalLpArray[i];
  1072 + if (oLp.isBxFb5_2()) {
  1073 + iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
  1074 + for (j = 1; j <= iAddBcCount; j++) {
  1075 + oBcChain1 = oLp.fnGetBcChainInfo(0);
  1076 + oBcChain2 = oLp.fnGetBcChainInfo(1);
  1077 +
  1078 + if (oBcChain1.bcount < oBcChain2.bcount) {
  1079 + iQindex = oBcChain1.s_b == 0 ? oBcChain1.s_q - 1 : oBcChain1.s_q;
  1080 + iBindex = oBcChain1.s_b == 0 ? 1 : 0;
  1081 + // 往车次链往前不能加,就往后加
  1082 + if (_fnGenerateBc(i, iQindex, iBindex)) {
  1083 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1084 + } else {
  1085 + iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
  1086 + iBindex = oBcChain1.e_b == 0 ? 1 : 0;
  1087 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1088 + }
  1089 +
  1090 + } else if (oBcChain1.bcount > oBcChain2.bcount) {
  1091 + iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
  1092 + iBindex = oBcChain2.s_b == 0 ? 1 : 0;
  1093 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1094 + } else {
  1095 + iQindex = oBcChain2.s_b == 0 ? oBcChain2.s_q - 1 : oBcChain2.s_q;
  1096 + iBindex = oBcChain2.s_b == 0 ? 1 : 0;
  1097 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1098 + }
  1099 + }
  1100 + }
  1101 + }
  1102 +
  1103 + },
  1104 +
  1105 + /**
  1106 + * 补其他分班班型班次。
  1107 + * 从车次链的后面开始加
  1108 + */
  1109 + fnCalcuLpBx_other: function() {
  1110 + // TODO:根据上标线的首班时间确定班型,小于05:59的做一休一,否则做二休一
  1111 + var oSt = _qIsUp ? _paramObj.getUpFirstDTimeObj() : _paramObj.getDownFirstDTimeObj();
  1112 + var iBxIndex = 4;
  1113 + if (oSt.isBefore(_paramObj.toTimeObj("05:59"))) {
  1114 + iBxIndex = 5;
  1115 + }
  1116 + // 计算做5休2班型所需的班次数
  1117 + var iQBcount = _aBxDesc[iBxIndex].fQCount;
  1118 + var iBxBcount = Math.round(iQBcount) * 2;
  1119 +
  1120 + var i;
  1121 + var j;
  1122 + var oLp;
  1123 + var iAddBcCount;
  1124 + var oBcChain1;
  1125 + var oBcChain2;
  1126 + var iQindex;
  1127 + var iBindex;
  1128 +
  1129 + for (i = 0; i < _internalLpArray.length; i++) {
  1130 + oLp = _internalLpArray[i];
  1131 + if (oLp.isBxFb() && !oLp.isBxFb5_2()) {
  1132 + iAddBcCount = iBxBcount - oLp.getBcArray().length; // 需要添加的班次数
  1133 + for (j = 1; j <= iAddBcCount; j++) {
  1134 + oBcChain1 = oLp.fnGetBcChainInfo(0);
  1135 + oBcChain2 = oLp.fnGetBcChainInfo(1);
  1136 +
  1137 + if (oBcChain1.bcount < oBcChain2.bcount) {
  1138 + iQindex = oBcChain1.e_b == 0 ? oBcChain1.e_q : oBcChain1.e_q + 1;
  1139 + iBindex = oBcChain1.e_b == 0 ? 1 : 0;
  1140 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1141 + } else if (oBcChain1.bcount > oBcChain2.bcount) {
  1142 + iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
  1143 + iBindex = oBcChain2.e_b == 0 ? 1 : 0;
  1144 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1145 + } else {
  1146 + iQindex = oBcChain2.e_b == 0 ? oBcChain2.e_q : oBcChain2.e_q + 1;
  1147 + iBindex = oBcChain2.e_b == 0 ? 1 : 0;
  1148 + _fnGenerateBcAndSetBc(i, iQindex, iBindex);
  1149 + }
  1150 + }
  1151 + }
  1152 + }
  1153 +
  1154 + },
  1155 +
  1156 + /**
  1157 + * 补充连班路牌班次。
  1158 + * 1、上标线,中标线中间的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向上标线起始班次靠拢
  1159 + * 2、中标线以下的连班路牌班次从早高峰班次一直拉到底,从早高峰班次向中标线起始班次靠拢
  1160 + */
  1161 + fnCalcuLpBx_lb: function() {
  1162 + // 补充连班的班次,参照上标线,中标线补充不足的班次
  1163 +
  1164 + var aLbLpindexes = []; // 除上标线,中标线的连班路牌索引
  1165 + var i;
  1166 + for (i = 0; i < _internalLpArray.length; i++) {
  1167 + if (_internalLpArray[i].isBxLb() && i != 0 && i != _iZbx_lpIndex) {
  1168 + aLbLpindexes.push(i);
  1169 + }
  1170 + }
  1171 +
  1172 + var oEndsj = // 结束时间
  1173 + _paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj()) ?
  1174 + _paramObj.getDownLastDTimeObj() :
  1175 + _paramObj.getUpLastDtimeObj();
  1176 +
  1177 + var oLp;
  1178 + var aMinbcPos;
  1179 + var oBc;
  1180 + var j;
  1181 + var iTempBcIndex;
  1182 +
  1183 + // 1、从最小班次开始,往后补充班次
  1184 + for (i = 0; i < aLbLpindexes.length; i++) {
  1185 + oLp = _internalLpArray[aLbLpindexes[i]];
  1186 +
  1187 + // 最小班次索引
  1188 + aMinbcPos = oLp.getMinBcObjPosition();
  1189 + // 使用纵向分隔补充班次,从最小班次向后补
  1190 + iTempBcIndex = aMinbcPos[1] == 0 ? 1 : 0;
  1191 + j = iTempBcIndex == 0 ? aMinbcPos[0] + 1 : aMinbcPos[0];
  1192 +
  1193 + while (j < _qCount) {
  1194 + while (iTempBcIndex <= 1) {
  1195 + oBc = _fnGenerateBc(aLbLpindexes[i], j, iTempBcIndex);
  1196 + if (oBc &&
  1197 + oBc.getFcTimeObj().isBefore(oEndsj) ) {
  1198 + oLp.setBc(j, iTempBcIndex, oBc);
  1199 + }
  1200 + iTempBcIndex++;
  1201 + }
  1202 + iTempBcIndex = 0;
  1203 + j++;
  1204 + }
  1205 +
  1206 + }
  1207 +
  1208 + // 2、上标线中标线之间的路牌,从最小的班次往前补充班次
  1209 +
  1210 + // 还要补充缺失的班次,差上标线几个班次要往前补上
  1211 + var iBccount;
  1212 + var iQindex;
  1213 + var iBindex;
  1214 + // 补上标线到中标线之间的连班路牌的班次
  1215 + for (i = 0; i < aLbLpindexes.length; i++) {
  1216 + if (aLbLpindexes[i] > 0 && aLbLpindexes[i] < _iZbx_lpIndex) {
  1217 + oLp = _internalLpArray[aLbLpindexes[i]];
  1218 + aMinbcPos = oLp.getMinBcObjPosition();
  1219 + iQindex = aMinbcPos[0];
  1220 + iBindex = aMinbcPos[1];
  1221 + iBccount = (iQindex - 1) * 2 + iBindex; // 距离上标线起始站点差几个班次
  1222 + for (j = 0; j < iBccount; j++) {
  1223 + if (iBindex == 0) {
  1224 + iQindex --;
  1225 + iBindex = 1;
  1226 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1227 + } else if (iBindex == 1) {
  1228 + iBindex --;
  1229 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1230 + }
  1231 + }
  1232 +
  1233 + }
  1234 +
  1235 + }
  1236 +
  1237 + // 3、中标线之后的路牌,从最小的班次往前补充班次
  1238 +
  1239 + // 补中标线以下的连班路牌的班次
  1240 + for (i = 0; i < aLbLpindexes.length; i++) {
  1241 + if (aLbLpindexes[i] > _iZbx_lpIndex) {
  1242 + oLp = _internalLpArray[aLbLpindexes[i]];
  1243 + aMinbcPos = oLp.getMinBcObjPosition();
  1244 + iQindex = aMinbcPos[0];
  1245 + iBindex = aMinbcPos[1];
  1246 + iBccount = (iQindex - 0) * 2 + iBindex - 1; // 距离上标线起始站点差几个班次
  1247 + for (j = 0; j < iBccount; j++) {
  1248 + if (iBindex == 0) {
  1249 + iQindex --;
  1250 + iBindex = 1;
  1251 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1252 + } else if (iBindex == 1) {
  1253 + iBindex --;
  1254 + _fnGenerateBcAndSetBc(aLbLpindexes[i], iQindex, iBindex);
  1255 + }
  1256 + }
  1257 + }
  1258 + }
  1259 +
  1260 + },
  1261 +
  1262 + /**
  1263 + * 计算末班车。
  1264 + * 1、将上下行拉成上下行两个班次列表(包括标记班次)
  1265 + * 2、分别找出离末班车发车时间最近的班次,并替换时间
  1266 + * 3、删除之后的班次
  1267 + */
  1268 + fnCalcuLastBc: function() {
  1269 + var i;
  1270 + var iTimeDiff;
  1271 + var iTempTime;
  1272 + var aBc;
  1273 + var oLastBcTime;
  1274 + var oLastBcIsUp;
  1275 + var iModifyIndex;
  1276 +
  1277 + // 查找末班车早的末班车时间和方向
  1278 + if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
  1279 + oLastBcTime = _paramObj.getUpLastDtimeObj();
  1280 + oLastBcIsUp = true;
  1281 + } else {
  1282 + oLastBcTime = _paramObj.getDownLastDTimeObj();
  1283 + oLastBcIsUp = false;
  1284 + }
  1285 +
  1286 + // 确定早的末班车时间
  1287 + aBc = _fnGetBcList(oLastBcIsUp);
  1288 + for (i = 0; i < aBc.length; i++) {
  1289 + iTempTime = oLastBcTime.diff(aBc[i].getFcTimeObj(), "m");
  1290 + if (iTimeDiff == undefined) {
  1291 + iTimeDiff = iTempTime;
  1292 + iModifyIndex = i;
  1293 + } else if (Math.abs(iTempTime) <= Math.abs(iTimeDiff)) {
  1294 + iTimeDiff = iTempTime;
  1295 + iModifyIndex = i;
  1296 + }
  1297 + }
  1298 + aBc[iModifyIndex].addMinuteToFcsj(iTimeDiff); // 替换成末班车时间
  1299 + aBc[iModifyIndex].fnSetDelFlag(false);
  1300 + aBc[iModifyIndex].fnSetIsLastBc(true);
  1301 + for (i = iModifyIndex + 1; i < aBc.length; i++) { // 删除多余班次
  1302 + _qIsUp == oLastBcIsUp ?
  1303 + aBc[i]._$$_internal_group_obj.setBc1(undefined) :
  1304 + aBc[i]._$$_internal_group_obj.setBc2(undefined);
  1305 + }
  1306 +
  1307 + // 查找末班车晚的末班车时间和方向
  1308 + if (_paramObj.getUpLastDtimeObj().isBefore(_paramObj.getDownLastDTimeObj())) {
  1309 + oLastBcTime = _paramObj.getDownLastDTimeObj();
  1310 + oLastBcIsUp = false;
  1311 + } else {
  1312 + oLastBcTime = _paramObj.getUpLastDtimeObj();
  1313 + oLastBcIsUp = true;
  1314 + }
  1315 + // 确定晚的末班车时间
  1316 + aBc = _fnGetBcList(oLastBcIsUp);
  1317 + var oBc;
  1318 + var aBcIndex;
  1319 + var iLpIndex;
  1320 + var iQIndex;
  1321 + var iBcIndex;
  1322 +
  1323 + iTimeDiff = undefined;
  1324 + for (i = 0; i < aBc.length; i++) {
  1325 + oBc = aBc[i];
  1326 + aBcIndex = _fnGetBcIndex(oBc);
  1327 +
  1328 + iLpIndex = aBcIndex[0];
  1329 + iQIndex = aBcIndex[2] == 0 ? aBcIndex[1] -1 : aBcIndex[1];
  1330 + iBcIndex = aBcIndex[2] == 0 ? 1 : 0;
  1331 +
  1332 + if (!_internalLpArray[iLpIndex].getBc(iQIndex, iBcIndex)) {
  1333 + continue;
  1334 + }
  1335 +
  1336 + iTempTime = oLastBcTime.diff(aBc[i].getFcTimeObj(), "m");
  1337 + if (iTimeDiff == undefined) {
  1338 + iTimeDiff = iTempTime;
  1339 + iModifyIndex = i;
  1340 + } else if (Math.abs(iTempTime) <= Math.abs(iTimeDiff)) {
  1341 + iTimeDiff = iTempTime;
  1342 + iModifyIndex = i;
  1343 + }
  1344 + }
  1345 + aBc[iModifyIndex].addMinuteToFcsj(iTimeDiff); // 替换成末班车时间
  1346 + aBc[iModifyIndex].fnSetDelFlag(false);
  1347 + aBc[iModifyIndex].fnSetIsLastBc(true);
  1348 + for (i = iModifyIndex + 1; i < aBc.length; i++) { // 删除多余班次
  1349 + _qIsUp == oLastBcIsUp ?
  1350 + aBc[i]._$$_internal_group_obj.setBc1(undefined) :
  1351 + aBc[i]._$$_internal_group_obj.setBc2(undefined);
  1352 + }
  1353 +
  1354 + },
  1355 +
  1356 + /**
  1357 + * 添加吃饭班次。
  1358 + */
  1359 + fnCalcuEatBc: function() {
  1360 + // 吃午饭时间范围,10:15 到 12:15
  1361 + // 吃晚饭时间范围,18:00 到 19:00
  1362 +
  1363 + if (!_paramObj.fnIsEat()) {
  1364 + return;
  1365 + }
  1366 +
  1367 + // 午饭index
  1368 + var aLEIndex;
  1369 + // 晚饭index
  1370 + var aDEIndex;
  1371 +
  1372 + // 所有吃饭都默认在一个方向,两个方向暂时不考虑
  1373 + if (_paramObj.fnIsUpEat()) {
  1374 + aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), true, false);
  1375 + aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), true, false);
  1376 + } else {
  1377 + aLEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("10:15"), false, true);
  1378 + aDEIndex = _internalLpArray[0].getQBcIndexWithFcTime(_paramObj.toTimeObj("18:00"), false, true);
  1379 + }
  1380 +
  1381 + // 午饭第几圈,第几个班次
  1382 + var iLEQIndex = aLEIndex[0];
  1383 + var iLEBIndex = aLEIndex[1];
  1384 + // 晚饭第几圈,第几个班次
  1385 + var iDEQIndex = aDEIndex[0];
  1386 + var iDEBIndex = aDEIndex[1];
  1387 +
  1388 + // 注意,本模型只有连班才有吃饭
  1389 +
  1390 + var i;
  1391 + var oLp;
  1392 + var aLbIndex = []; // 连班班型的路牌索引
  1393 + for (i = 0; i < _internalLpArray.length; i++) {
  1394 + oLp = _internalLpArray[i];
  1395 + if (oLp.isBxLb()) {
  1396 + aLbIndex.push(i);
  1397 + }
  1398 + }
  1399 +
  1400 + var iLTime;
  1401 + var iDtime;
  1402 + var j;
  1403 + for (i = 0; i < aLbIndex.length; i++) {
  1404 + oLp = _internalLpArray[aLbIndex[i]];
  1405 +
  1406 + // 午饭
  1407 + iLTime = oLp.fnAddEatBc(iLEQIndex, iLEBIndex, _factory, _paramObj);
  1408 + // 晚饭
  1409 + iDtime = oLp.fnAddEatBc(iDEQIndex, iDEBIndex, _factory, _paramObj);
  1410 +
  1411 + if (i == aLbIndex.length - 1) {
  1412 + for (j = aLbIndex[i]; j < _internalLpArray.length; j++) {
  1413 + oLp = _internalLpArray[j];
  1414 + if (oLp.isBxFb()) { // 5休2班型不调整
  1415 + // 修正午饭之后路牌班次的发车时间
  1416 + oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
  1417 + oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
  1418 + }
  1419 + }
  1420 + } else {
  1421 + for (j = aLbIndex[i]; j < aLbIndex[i + 1]; j++) {
  1422 + oLp = _internalLpArray[j];
  1423 + if (oLp.isBxFb()) {
  1424 + // 修正午饭之后路牌班次的发车时间
  1425 + oLp.fnAddMinuteToBcFcsj(iLEQIndex, iLEBIndex, iLTime);
  1426 + oLp.fnAddMinuteToBcFcsj(iDEQIndex, iDEBIndex, iDtime);
  1427 + }
  1428 + }
  1429 + }
  1430 + }
  1431 +
  1432 + },
  1433 +
  1434 + /**
  1435 + * 补每个路牌的其他班次(进出场,例保班次)。
  1436 + */
  1437 + fnCalcuOtherBc_: function() {
  1438 + var i;
  1439 + var _lpObj;
  1440 + var _minBcIndex;
  1441 + var _maxBcIndex;
  1442 + var _minBc;
  1443 + var _maxBc;
  1444 + var _otherbc = [];
  1445 + var _oFbbc;
  1446 +
  1447 + for (i = 0; i < _internalLpArray.length; i++) {
  1448 + _lpObj = _internalLpArray[i];
  1449 + _minBcIndex = _lpObj.getMinBcObjPosition();
  1450 + _maxBcIndex = _lpObj.getMaxBcObjPosition();
  1451 + _minBc = _lpObj.getBc(_minBcIndex[0], _minBcIndex[1]);
  1452 + _maxBc = _lpObj.getBc(_maxBcIndex[0], _maxBcIndex[1]);
  1453 +
  1454 + _otherbc = [];
  1455 + _otherbc.push(_factory.createBcObj(
  1456 + _lpObj, "bd", true, 1,
  1457 + _minBc.getFcTimeObj(),
  1458 + _paramObj
  1459 + ));
  1460 + _otherbc.push(_factory.createBcObj(
  1461 + _lpObj, "out", true, 1,
  1462 + _minBc.getFcTimeObj(),
  1463 + _paramObj
  1464 + ));
  1465 +
  1466 + _maxBc.setArrTimeObj(_paramObj.addMinute(_maxBc.getFcTimeObj(), _maxBc.getBcTime()));
  1467 + _maxBc.setStopTime(0);
  1468 + _otherbc.push(_factory.createBcObj(
  1469 + _lpObj, "in", true, 1,
  1470 + _maxBc.getArrTimeObj(),
  1471 + _paramObj
  1472 + ));
  1473 + _otherbc.push(_factory.createBcObj(
  1474 + _lpObj, "lc", true, 1,
  1475 + _maxBc.getArrTimeObj(),
  1476 + _paramObj
  1477 + ));
  1478 +
  1479 + // 5休2分班出场例保班次
  1480 + if (_lpObj.isBxFb5_2()) {
  1481 + _oFbbc = _lpObj.getBc(
  1482 + _lpObj.fnGetBcChainInfo(1)["s_q"],
  1483 + _lpObj.fnGetBcChainInfo(1)["s_b"]
  1484 + );
  1485 +
  1486 + _otherbc.push(_factory.createBcObj(
  1487 + _lpObj, "bd", true, 1,
  1488 + _oFbbc.getFcTimeObj(),
  1489 + _paramObj
  1490 + ));
  1491 + _otherbc.push(_factory.createBcObj(
  1492 + _lpObj, "out", true, 1,
  1493 + _oFbbc.getFcTimeObj(),
  1494 + _paramObj
  1495 + ));
  1496 + }
  1497 +
  1498 + _lpObj.addOtherBcArray(_otherbc);
  1499 + }
  1500 +
  1501 + },
  1502 +
  1503 + /**
  1504 + * 补每个路牌的其他班次(进出场,例保班次)
  1505 + * 所有的车次链前后都加进出场、报道班次
  1506 + */
  1507 + fnCalcuOtherBc: function() {
  1508 + var i;
  1509 + var j;
  1510 + var iBcChainCount;
  1511 + var oLp;
  1512 + var aOtherBc;
  1513 + var oStartBc;
  1514 + var oEndBc;
  1515 +
  1516 + for (i = 0; i < _internalLpArray.length; i++) {
  1517 + aOtherBc = [];
  1518 + oLp = _internalLpArray[i];
  1519 + iBcChainCount = oLp.fnGetBcChainCount();
  1520 +
  1521 + if (iBcChainCount == 1) { // 只有一个车次链,是连班班型
  1522 + // 头部要添加出场,例保班次
  1523 + oStartBc = oLp.getBc(
  1524 + oLp.fnGetBcChainInfo(0)["s_q"],
  1525 + oLp.fnGetBcChainInfo(0)["s_b"]
  1526 + );
  1527 + aOtherBc.push(_factory.createBcObj(
  1528 + oLp, "bd", true, 1,
  1529 + oStartBc.getFcTimeObj(),
  1530 + _paramObj
  1531 + ));
  1532 + aOtherBc.push(_factory.createBcObj(
  1533 + oLp, "out", true, 1,
  1534 + oStartBc.getFcTimeObj(),
  1535 + _paramObj
  1536 + ));
  1537 +
  1538 + // 尾部需添加进场,例保班次
  1539 + oEndBc = oLp.getBc(
  1540 + oLp.fnGetBcChainInfo(0)["e_q"],
  1541 + oLp.fnGetBcChainInfo(0)["e_b"]
  1542 + );
  1543 + aOtherBc.push(_factory.createBcObj(
  1544 + oLp, "in", true, 1,
  1545 + oEndBc.getArrTimeObj(),
  1546 + _paramObj
  1547 + ));
  1548 + aOtherBc.push(_factory.createBcObj(
  1549 + oLp, "lc", true, 1,
  1550 + oEndBc.getArrTimeObj(),
  1551 + _paramObj
  1552 + ));
  1553 + } else if (iBcChainCount == 2) { // 两个车次链,是分班班型
  1554 + // 第一个车次链开头有出场,报到班次,车次链结尾只有进场班次
  1555 + oStartBc = oLp.getBc(
  1556 + oLp.fnGetBcChainInfo(0)["s_q"],
  1557 + oLp.fnGetBcChainInfo(0)["s_b"]
  1558 + );
  1559 + aOtherBc.push(_factory.createBcObj(
  1560 + oLp, "bd", true, 1,
  1561 + oStartBc.getFcTimeObj(),
  1562 + _paramObj
  1563 + ));
  1564 + aOtherBc.push(_factory.createBcObj(
  1565 + oLp, "out", true, 1,
  1566 + oStartBc.getFcTimeObj(),
  1567 + _paramObj
  1568 + ));
  1569 +
  1570 + oEndBc = oLp.getBc(
  1571 + oLp.fnGetBcChainInfo(0)["e_q"],
  1572 + oLp.fnGetBcChainInfo(0)["e_b"]
  1573 + );
  1574 + aOtherBc.push(_factory.createBcObj(
  1575 + oLp, "in", true, 1,
  1576 + oEndBc.getArrTimeObj(),
  1577 + _paramObj
  1578 + ));
  1579 +
  1580 + // 第二个车次链开头只有出场班次,车次链结尾有进场,报到班次
  1581 + oStartBc = oLp.getBc(
  1582 + oLp.fnGetBcChainInfo(1)["s_q"],
  1583 + oLp.fnGetBcChainInfo(1)["s_b"]
  1584 + );
  1585 + aOtherBc.push(_factory.createBcObj(
  1586 + oLp, "out", true, 1,
  1587 + oStartBc.getFcTimeObj(),
  1588 + _paramObj
  1589 + ));
  1590 +
  1591 + oEndBc = oLp.getBc(
  1592 + oLp.fnGetBcChainInfo(1)["e_q"],
  1593 + oLp.fnGetBcChainInfo(1)["e_b"]
  1594 + );
  1595 + aOtherBc.push(_factory.createBcObj(
  1596 + oLp, "in", true, 1,
  1597 + oEndBc.getArrTimeObj(),
  1598 + _paramObj
  1599 + ));
  1600 + aOtherBc.push(_factory.createBcObj(
  1601 + oLp, "lc", true, 1,
  1602 + oEndBc.getArrTimeObj(),
  1603 + _paramObj
  1604 + ));
  1605 +
  1606 +
  1607 + } else {
  1608 + // 2个车次链以上,暂时没有此班型
  1609 + }
  1610 +
  1611 + oLp.addOtherBcArray(aOtherBc);
  1612 + }
  1613 + },
  1614 +
  1615 + /**
  1616 + * 祛除上标线开头的删除标记的班次。
  1617 + */
  1618 + fnRemoveDelFirstFlagBc: function() {
  1619 + var oLp = _internalLpArray[0];
  1620 + var aMinBcIndex = oLp.getMinBcObjPosition();
  1621 + if (oLp.getBc(aMinBcIndex[0], aMinBcIndex[1]).fnIsDelFlag()) {
  1622 + oLp.removeBc(aMinBcIndex[0], aMinBcIndex[1]);
  1623 + }
  1624 + },
  1625 + /**
  1626 + * 祛除上标线结尾的删除标记的班次。
  1627 + */
  1628 + fnRemoveDelLastFlagBc: function() {
  1629 + var oLp = _internalLpArray[0];
  1630 + var aMaxBcIndex = oLp.getMaxBcObjPosition();
  1631 + if (oLp.getBc(aMaxBcIndex[0], aMaxBcIndex[1]).fnIsDelFlag()) {
  1632 + oLp.removeBc(aMaxBcIndex[0], aMaxBcIndex[1]);
  1633 + }
  1634 + },
  1635 +
  1636 + /**
  1637 + * 调整路牌班次间隔(核准周转时间,停站时间)。
  1638 + * @param iFre int 迭代次数
  1639 + */
  1640 + fnAdjustLpBcInterval: function(iFre) {
  1641 + if (iFre > 0) {
  1642 + for (var i = 0; i < _internalLpArray.length; i++) {
  1643 + _internalLpArray[i].fnAdjustBcInterval(
  1644 + this.fnCalcuAverPeakStopTime(),
  1645 + this.fnCalcuAverTroughStopTime(),
  1646 + _paramObj);
  1647 + }
  1648 +
  1649 + this.fnAdjustLpBcInterval(iFre - 1);
  1650 + }
  1651 + },
  1652 +
  1653 + /**
  1654 + * 调整班次间隔。
  1655 + * @param bIsUp 是否上行
  1656 + * @param oStartTime 开始时间对象
  1657 + * @param iFre 迭代次数
  1658 + */
  1659 + fnAdjustBcInterval2_: function(bIsUp, oStartTime, iFre) {
  1660 + if (iFre > 0) {
  1661 + var aBc = _fnGetBcList2(bIsUp, oStartTime); // 指定方向的班次列表
  1662 + aBc.sort(function(o1, o2) {
  1663 + if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
  1664 + return -1;
  1665 + } else {
  1666 + return 1;
  1667 + }
  1668 + });
  1669 + var i;
  1670 + var j;
  1671 +
  1672 + var iBcCountOfGroup = 3; // 3个班次取一次计算
  1673 + var aBcOfGroup; // 3个班次列表
  1674 + var aBcIntervalOfGroup; // 班次间隔列表,如:3个班次,2个间隔
  1675 +
  1676 + for (i = 0; i <= aBc.length - iBcCountOfGroup; i++) {
  1677 + aBcOfGroup = [];
  1678 + aBcIntervalOfGroup = [];
  1679 + for (j = i; j < i + iBcCountOfGroup; j++) {
  1680 + aBcOfGroup.push(aBc[j]);
  1681 + }
  1682 +
  1683 + for (j = 0; j < aBcOfGroup.length; j++) {
  1684 + if (j < aBcOfGroup.length - 1) {
  1685 + aBcIntervalOfGroup.push(aBcOfGroup[j + 1].getFcTimeObj().diff(
  1686 + aBcOfGroup[j].getFcTimeObj(), "m"));
  1687 + }
  1688 + }
  1689 +
  1690 + if (aBcIntervalOfGroup[0] < 19) {
  1691 + aBcOfGroup[1].addMinuteToFcsj(1);
  1692 + } else if (aBcIntervalOfGroup[0] > 20) {
  1693 + aBcOfGroup[1].addMinuteToFcsj(-1);
  1694 + } else {
  1695 + if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
  1696 + //continue;
  1697 + } else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
  1698 + aBcOfGroup[1].addMinuteToFcsj(-1);
  1699 + } else {
  1700 + aBcOfGroup[1].addMinuteToFcsj(1);
  1701 + }
  1702 + }
  1703 +
  1704 + }
  1705 +
  1706 + this.fnAdjustBcInterval2(bIsUp, oStartTime, iFre - 1);
  1707 + }
  1708 + },
  1709 +
  1710 + /**
  1711 + * 调整班次间隔。
  1712 + * @param boolean isUp 是否上行
  1713 + * @param oStartTime 开始时间对象
  1714 + * @param fre int 迭代次数
  1715 + */
  1716 + fnAdjustBcInterval: function(isUp, oStartTime, fre) {
  1717 + if (fre > 0) {
  1718 + var aBc = !oStartTime ? _fnGetBcList(isUp) : _fnGetBcList2(isUp, oStartTime); // 指定方向的班次列表
  1719 +
  1720 + aBc.sort(function(o1, o2) {
  1721 + if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
  1722 + return -1;
  1723 + } else {
  1724 + return 1;
  1725 + }
  1726 + });
  1727 +
  1728 + var i;
  1729 + var j;
  1730 +
  1731 + var iBcCountOfGroup = 3; // 3个班次取一次计算
  1732 + var aBcOfGroup; // 3个班次列表
  1733 + var aBcIntervalOfGroup; // 班次间隔列表,如:3个班次,2个间隔
  1734 + var oBcFcTime; // 班次发车时间
  1735 +
  1736 + for (i = 0; i <= aBc.length - iBcCountOfGroup; i++) {
  1737 + aBcOfGroup = [];
  1738 + aBcIntervalOfGroup = [];
  1739 + for (j = i; j < i + iBcCountOfGroup; j++) {
  1740 + aBcOfGroup.push(aBc[j]);
  1741 + }
  1742 +
  1743 + for (j = 0; j < aBcOfGroup.length; j++) {
  1744 + if (j < aBcOfGroup.length - 1) {
  1745 + aBcIntervalOfGroup.push(aBcOfGroup[j + 1].getFcTimeObj().diff(
  1746 + aBcOfGroup[j].getFcTimeObj(), "m"));
  1747 + }
  1748 + }
  1749 +
  1750 + // 判定规则
  1751 + oBcFcTime = aBcOfGroup[1].getFcTimeObj();
  1752 +
  1753 + // 第一个班次发车时间不动,根据间隔,调整中间一个班次
  1754 + // 如果3个班次2个间隔时间差1分钟,不调整
  1755 + // 如果第一个间隔大,调整第二个班次往前1分钟
  1756 + // 如果第二个间隔大,调整第二个班次往后1分钟
  1757 +
  1758 + if (_paramObj.isTroughBc(oBcFcTime) &&
  1759 + aBcIntervalOfGroup[0] > _paramObj.getTroughMaxFcjx()) {
  1760 + aBcOfGroup[1].addMinuteToFcsj(-1);
  1761 + }
  1762 +
  1763 + //else if (_paramObj.isMPeakBc(oBcFcTime) &&
  1764 + // aBcIntervalOfGroup[0] < _paramObj.getMPeakMinFcjx()) {
  1765 + // aBcOfGroup[1].addMinuteToFcsj(1);
  1766 + //} else if (_paramObj.isMPeakBc(oBcFcTime) &&
  1767 + // aBcIntervalOfGroup[0] > _paramObj.getMPeakMaxFcjx()) {
  1768 + // aBcOfGroup[1].addMinuteToFcsj(-1);
  1769 + //} else if (_paramObj.isEPeakBc(oBcFcTime) &&
  1770 + // aBcIntervalOfGroup[0] < _paramObj.getEPeakMinFcjx()) {
  1771 + // aBcOfGroup[1].addMinuteToFcsj(1);
  1772 + //} else if (_paramObj.isEPeakBc(oBcFcTime) &&
  1773 + // aBcIntervalOfGroup[0] > _paramObj.getEPeakMaxFcjx()) {
  1774 + // aBcOfGroup[1].addMinuteToFcsj(-1);
  1775 + //}
  1776 +
  1777 +
  1778 + else {
  1779 + if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
  1780 + //continue;
  1781 + } else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
  1782 + aBcOfGroup[1].addMinuteToFcsj(-1);
  1783 + } else {
  1784 + aBcOfGroup[1].addMinuteToFcsj(1);
  1785 + }
  1786 + }
  1787 +
  1788 + //if (Math.abs(aBcIntervalOfGroup[0] - aBcIntervalOfGroup[1]) <= 1) {
  1789 + // //continue;
  1790 + //} else if (aBcIntervalOfGroup[0] > aBcIntervalOfGroup[1]) {
  1791 + // aBcOfGroup[1].addMinuteToFcsj(-1);
  1792 + //} else {
  1793 + // aBcOfGroup[1].addMinuteToFcsj(1);
  1794 + //}
  1795 +
  1796 +
  1797 + }
  1798 +
  1799 + this.fnAdjustBcInterval(isUp, oStartTime, fre - 1);
  1800 + }
  1801 +
  1802 + },
  1803 +
  1804 + /**
  1805 + * 调整班次间隔(平均间隔)。
  1806 + * @param bIsUp 是否上行
  1807 + * @param oStartTime 开始时间对象
  1808 + */
  1809 + fnAdjustBcInterval2_avg: function(bIsUp, oStartTime) {
  1810 + var aBc = !oStartTime ? _fnGetBcList(bIsUp) : _fnGetBcList2(bIsUp, oStartTime); // 指定方向的班次列表
  1811 + aBc.sort(function(o1, o2) {
  1812 + if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
  1813 + return -1;
  1814 + } else {
  1815 + return 1;
  1816 + }
  1817 + });
  1818 +
  1819 + var j;
  1820 + var iCount = aBc.length - 1;
  1821 + var iC1 = Math.floor(aBc[aBc.length - 1].getFcTimeObj().diff(aBc[0].getFcTimeObj(), "m") / iCount);
  1822 + var iC2 = aBc[aBc.length - 1].getFcTimeObj().diff(aBc[0].getFcTimeObj(), "m") % iCount;
  1823 + var iTempTime;
  1824 +
  1825 + for (j = 0; j < iCount - iC2; j++) {
  1826 + iTempTime = aBc[j + 1].getFcTimeObj().diff(aBc[j].getFcTimeObj(), "m");
  1827 + aBc[j + 1].addMinuteToFcsj(iC1 - iTempTime);
  1828 + }
  1829 + for (j = 0; j < iC2; j++) {
  1830 + iTempTime = aBc[iCount - iC2 + j + 1].getFcTimeObj().diff(aBc[iCount - iC2 + j].getFcTimeObj(), "m");
  1831 + aBc[iCount - iC2 + j + 1].addMinuteToFcsj(iC1 + 1 - iTempTime);
  1832 + }
  1833 +
  1834 + },
  1835 +
  1836 + /**
  1837 + * 计算高峰平均停站时间。
  1838 + */
  1839 + fnCalcuAverPeakStopTime: function() {
  1840 + var i;
  1841 + var j;
  1842 + var aBc;
  1843 + var iBcCount = 0;
  1844 + var iSum = 0;
  1845 + for (i = 0; i < _internalLpArray.length; i++) {
  1846 + aBc = _internalLpArray[i].getBcArray();
  1847 +
  1848 + for (j = 0; j < aBc.length; j++) {
  1849 + if (!_paramObj.isTroughBc(aBc[j].getArrTimeObj())) {
  1850 + iBcCount ++;
  1851 + iSum += aBc[j].getStopTime();
  1852 + }
  1853 + }
  1854 + }
  1855 +
  1856 + return Math.floor(iSum / iBcCount);
  1857 + },
  1858 +
  1859 + /**
  1860 + * 计算低谷平均停站时间。
  1861 + */
  1862 + fnCalcuAverTroughStopTime: function() {
  1863 + var i;
  1864 + var j;
  1865 + var aBc;
  1866 + var iBcCount = 0;
  1867 + var iSum = 0;
  1868 + for (i = 0; i < _internalLpArray.length; i++) {
  1869 + aBc = _internalLpArray[i].getBcArray();
  1870 + for (j = 0; j < aBc.length; j++) {
  1871 + if (_paramObj.isTroughBc(aBc[j].getArrTimeObj())) {
  1872 + iBcCount ++;
  1873 + iSum += aBc[j].getStopTime();
  1874 + }
  1875 + }
  1876 + }
  1877 +
  1878 + return Math.floor(iSum / iBcCount);
  1879 + },
  1880 +
  1881 + //------------- 其他方法 -------------//
  1882 + /**
  1883 + * 内部数据转化成显示用的班次数组。
  1884 + */
  1885 + fnToGanttBcArray: function() {
  1886 + var aAllBc = [];
  1887 + var aLpBc = [];
  1888 + var aEatBc = [];
  1889 + var oLp;
  1890 + var i;
  1891 + var j;
  1892 +
  1893 + for (i = 0; i < _internalLpArray.length; i++) {
  1894 + oLp = _internalLpArray[i];
  1895 + aLpBc = [];
  1896 + aLpBc = aLpBc.concat(oLp.getOtherBcArray(), oLp.getBcArray());
  1897 +
  1898 + aEatBc = [];
  1899 + // 根据班次的吃饭时间添加吃饭班次
  1900 + for (j = 0; j < aLpBc.length; j++) {
  1901 + if (aLpBc[j].fnGetEatTime() > 0) {
  1902 + aEatBc.push(_factory.createBcObj(
  1903 + oLp,
  1904 + "cf",
  1905 + !aLpBc[j].isUp(), // 和上一个班次方向相反
  1906 + 1,
  1907 + _paramObj.addMinute(aLpBc[j].getArrTimeObj(), aLpBc[j].getStopTime()), // 使用上一个班次的到达时间作为开始时间
  1908 + _paramObj
  1909 + ));
  1910 + }
  1911 + }
  1912 + aLpBc = aLpBc.concat(aEatBc);
  1913 +
  1914 + // 按照发车时间排序
  1915 + aLpBc.sort(function(o1, o2) {
  1916 + if (o1.getFcTimeObj().isBefore(o2.getFcTimeObj())) {
  1917 + return -1;
  1918 + } else {
  1919 + return 1;
  1920 + }
  1921 + });
  1922 +
  1923 + // 重新赋值fcno
  1924 + for (j = 0; j < aLpBc.length; j++) {
  1925 + aLpBc[j].fnSetFcno(j + 1);
  1926 + }
  1927 +
  1928 + aAllBc = aAllBc.concat(aLpBc);
  1929 + }
  1930 +
  1931 + var aGanttBc = [];
  1932 + for (i = 0; i < aAllBc.length; i++) {
  1933 + aGanttBc.push(aAllBc[i].toGanttBcObj());
  1934 + }
  1935 +
  1936 + return aGanttBc;
  1937 + }
  1938 +
  1939 + };
1927 1940 };
1928 1941 \ No newline at end of file
... ...