Commit be2c4b67f2bb4692ee1b5c286ffe67aa4dd9b451

Authored by 徐烜
1 parent ceb8a823

时刻表v2.3

基本实现让班次间隔平滑过渡,但是有些周转班次时间还是有问题,以后修正
1、将吃饭时间作为班次对象的一个属性,类似停站时间,参与计算下一个班次的发车时间,在最后绘制gantt图的时候再动态添加吃饭班次
2、修正从头拉班次的算法(主要是创建上标线,中标线的方法),修正终止条件,只需判定下一个班次的发车时间是否超过endtime,不需再判定下一个班次的到达时间是否超过endtime
3、添加调整单个路牌横向班次周转时间方法(简单调整停站时间,这个方法以后还要改)
4、添加调整所有纵向班次的间隔时间方法,采用3个班次2个间隔趋于平均,让后分别迭代两个方向上的所有班次(算法没有考虑横向间隔-与第3点联动,但是初期试验下来效果还可以,以后优化)
5、添加调整指定时间后所有班次间隔方法,采用平均化所有班次间隔(主要处理晚高峰过后的班次,19:50后的班次,初期效果还可以,以后优化)
6、修改确定末班车班次的方法(比之前的效果好,以后再优化)
7、将删除标记参数分为两步,删除开头的,删除结尾的,将删除结尾的方法调用放在确定末班车之后,因为结尾的删除标记班次可能会被修正为末班车

Too many changes to show.

To preserve performance only 3 of 5 files are displayed.

src/main/resources/static/pages/base/timesmodel/js/v2/ParameterObj.js
@@ -895,7 +895,7 @@ var ParameterObj = function() { @@ -895,7 +895,7 @@ var ParameterObj = function() {
895 }, 895 },
896 896
897 /** 897 /**
898 - * 获取固定的停站时间(固定停站时间都是选的最大值 898 + * 获取固定的停站时间(固定停站时间都是选的最大值,非平均停站
899 * @param oTimeObj 时间对象 899 * @param oTimeObj 时间对象
900 * @param bIsUp 是否上行 900 * @param bIsUp 是否上行
901 * @param iXXTime 行驶时间 901 * @param iXXTime 行驶时间
@@ -1082,6 +1082,85 @@ var ParameterObj = function() { @@ -1082,6 +1082,85 @@ var ParameterObj = function() {
1082 }, 1082 },
1083 1083
1084 /** 1084 /**
  1085 + * 获取固定的停站时间(固定停站时间都是选的最小值,非平均停站)
  1086 + * @param oTimeObj 时间对象
  1087 + * @param bIsUp 是否上行
  1088 + * @returns int 停站时间
  1089 + */
  1090 + fnCalcuFixedMinStopNumber: function(oTimeObj, bIsUp) {
  1091 + _validInternal(); // 验证
  1092 + var oParam = this;
  1093 +
  1094 + // 双向停站
  1095 + if (oParam.isTwoWayStop()) {
  1096 + if (bIsUp) { // 上行
  1097 + if (this.isMPeakBc(oTimeObj)) { // 早高峰
  1098 + return 3;
  1099 + } else if (this.isEPeakBc(oTimeObj)) { // 晚高峰
  1100 + return 3;
  1101 + } else { // 低谷
  1102 + if (this.isTroughBeforMPeakStartBc(oTimeObj)) { // 早高峰开始前
  1103 + return 10;
  1104 + } else if (this.isTroughAfterEPeakEndBc(oTimeObj)) { // 晚高峰结束后
  1105 + return 10;
  1106 + } else { // 早高峰,晚高峰之间
  1107 + return 10;
  1108 + }
  1109 + }
  1110 +
  1111 + } else { // 下行
  1112 + if (this.isMPeakBc(oTimeObj)) { // 早高峰
  1113 + return 3;
  1114 + } else if (this.isEPeakBc(oTimeObj)) { // 晚高峰
  1115 + return 3;
  1116 + } else { // 低谷
  1117 + if (this.isTroughBeforMPeakStartBc(oTimeObj)) { // 早高峰开始前
  1118 + return 10;
  1119 + } else if (this.isTroughAfterEPeakEndBc(oTimeObj)) { // 晚高峰结束后
  1120 + return 10;
  1121 + } else { // 早高峰,晚高峰之间
  1122 + return 10;
  1123 + }
  1124 + }
  1125 + }
  1126 + } else { // 主站停站
  1127 + if (bIsUp == oParam.isUpOneWayStop()) {
  1128 + if (bIsUp) { // 上行
  1129 + if (this.isMPeakBc(oTimeObj)) { // 早高峰
  1130 + return 2;
  1131 + } else if (this.isEPeakBc(oTimeObj)) { // 晚高峰
  1132 + return 2;
  1133 + } else { // 低谷
  1134 + if (this.isTroughBeforMPeakStartBc(oTimeObj)) { // 早高峰开始前
  1135 + return 10;
  1136 + } else if (this.isTroughAfterEPeakEndBc(oTimeObj)) { // 晚高峰结束后
  1137 + return 10;
  1138 + } else { // 早高峰,晚高峰之间
  1139 + return 10;
  1140 + }
  1141 + }
  1142 + } else { // 下行
  1143 + if (this.isMPeakBc(oTimeObj)) { // 早高峰
  1144 + return 2;
  1145 + } else if (this.isEPeakBc(oTimeObj)) { // 晚高峰
  1146 + return 2;
  1147 + } else { // 低谷
  1148 + if (this.isTroughBeforMPeakStartBc(oTimeObj)) { // 早高峰开始前
  1149 + return 10;
  1150 + } else if (this.isTroughAfterEPeakEndBc(oTimeObj)) { // 晚高峰结束后
  1151 + return 10;
  1152 + } else { // 早高峰,晚高峰之间
  1153 + return 10;
  1154 + }
  1155 + }
  1156 + }
  1157 + } else { // 副站停战,2到3分钟
  1158 + return 2;
  1159 + }
  1160 + }
  1161 + },
  1162 +
  1163 + /**
1085 * 获取行驶时间。 1164 * 获取行驶时间。
1086 * @param timeObj 班次时间字符串 1165 * @param timeObj 班次时间字符串
1087 * @param isUp 是否上行 1166 * @param isUp 是否上行
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalBcObj.js
@@ -32,6 +32,7 @@ var InternalBcObj = function( @@ -32,6 +32,7 @@ var InternalBcObj = function(
32 this._$_bcsj = otherParamObj.bcsj; // 班次历时 32 this._$_bcsj = otherParamObj.bcsj; // 班次历时
33 this._$_arrtime = otherParamObj.arrtime; // 到达时间对象 33 this._$_arrtime = otherParamObj.arrtime; // 到达时间对象
34 this._$_stoptime = otherParamObj.stoptime; // 停站时间 34 this._$_stoptime = otherParamObj.stoptime; // 停站时间
  35 + this._$_iEatTime = 0; // 吃饭时间
35 this._$_tccid = otherParamObj.tccid; // 停车场id 36 this._$_tccid = otherParamObj.tccid; // 停车场id
36 this._$_ttinfoid = otherParamObj.ttinfoid; // 时刻表id 37 this._$_ttinfoid = otherParamObj.ttinfoid; // 时刻表id
37 this._$_xlid = otherParamObj.xl; // 线路id 38 this._$_xlid = otherParamObj.xl; // 线路id
@@ -45,6 +46,13 @@ var InternalBcObj = function( @@ -45,6 +46,13 @@ var InternalBcObj = function(
45 46
46 //------------------- get/set 方法 -------------------// 47 //------------------- get/set 方法 -------------------//
47 48
  49 +InternalBcObj.prototype.fnSetEatTime = function(iTime) {
  50 + this._$_iEatTime = iTime;
  51 +};
  52 +InternalBcObj.prototype.fnGetEatTime = function() {
  53 + return this._$_iEatTime;
  54 +};
  55 +
48 InternalBcObj.prototype.fnSetDelFlag = function(bFlag) { 56 InternalBcObj.prototype.fnSetDelFlag = function(bFlag) {
49 this._$_bDelFlag = bFlag; 57 this._$_bDelFlag = bFlag;
50 }; 58 };
src/main/resources/static/pages/base/timesmodel/js/v2/core/InternalLpObj.js
1 -/**  
2 - * 内部路牌对象。  
3 - * @constructor  
4 - */  
5 -var InternalLpObj = function(  
6 - orilpObj, // 原始路牌对象  
7 - qCount, // 总共多少圈  
8 - isUp // 圈是以上行开始还是下行开始  
9 -) {  
10 - // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)  
11 - this._$$_orign_lp_obj = orilpObj;  
12 -  
13 - this._$_isUp = isUp;  
14 -  
15 - // 路牌的圈数,注意每个路牌的圈数都是一致的,  
16 - // 但并不是每一圈都有值  
17 - // 第1圈从上标线开始  
18 - // 第0圈表示中标线的第一个班次组成的半圈  
19 - // 有多少圈根据最终迭代的结果来看  
20 - this._$_qCount = qCount;  
21 - // 保存的是 InternalGroupBcObj 对象  
22 - this._$_groupBcArray = new Array(qCount);  
23 -  
24 - var i;  
25 - for (i = 0; i < this._$_qCount; i++) {  
26 - this._$_groupBcArray[i] = new InternalGroupObj(  
27 - this, this._$_isUp, undefined, undefined);  
28 - }  
29 -  
30 - // 距离上一个路牌的最小发车间隔时间  
31 - // 用于纵向添加班次的时候使用  
32 - // 默认第一个路牌为0  
33 - this._$_minVerticalIntervalTime = 0;  
34 -  
35 - // 详细记录每圈每个方向上的发车间隔时间  
36 - // 第一维度表示圈数,第二维度表示第一个方向,第二个方向  
37 - // 第一个方向是否上行由 _$_isUp 决定  
38 - // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔  
39 - // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔  
40 - this._$_aVerticalIntervalTime = new Array(this._$_qCount);  
41 - var i;  
42 - for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {  
43 - this._$_aVerticalIntervalTime[i] = new Array(2);  
44 - }  
45 -  
46 - // 班型的相关变量  
47 - this._$_bx_isLb = false; // 是否连班  
48 - this._$_bx_isfb = false; // 是否分班  
49 - this._$_bx_isfb_5_2 = false; // 是否5休2分班  
50 - this._$_bx_desc; // 班型描述(默认为路牌编号)  
51 -  
52 - // 其他班次(进出场,例包,吃饭等),TODO:以后再拆  
53 - this._$_other_bc_array = [];  
54 -  
55 - // TODO:  
56 -  
57 -};  
58 -  
59 -//------------------- get/set 方法 -------------------//  
60 -  
61 -InternalLpObj.prototype.getOtherBcArray = function() {  
62 - return this._$_other_bc_array;  
63 -};  
64 -InternalLpObj.prototype.addOtherBcArray = function(ba) {  
65 - this._$_other_bc_array = this._$_other_bc_array.concat(ba);  
66 -};  
67 -  
68 -/**  
69 - * 获取圈  
70 - * @param qIndex 圈index  
71 - */  
72 -InternalLpObj.prototype.getGroup = function(qIndex) {  
73 - return this._$_groupBcArray[qIndex];  
74 -};  
75 -  
76 -/**  
77 - * 获取班次。  
78 - * @param qIndex 第几圈  
79 - * @param bcIndex 第几个班次  
80 - */  
81 -InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {  
82 - var group = this._$_groupBcArray[qIndex];  
83 - var bc;  
84 - if (bcIndex == 0) {  
85 - bc = group.getBc1();  
86 - } else if (bcIndex == 1) {  
87 - bc = group.getBc2();  
88 - }  
89 - return bc;  
90 -};  
91 -  
92 -/**  
93 - * 在具体位置设置班次。  
94 - * @param qIndex 第几圈  
95 - * @param bcIndex 第几个班次  
96 - * @param bc 班次对象  
97 - */  
98 -InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {  
99 - var group = this._$_groupBcArray[qIndex];  
100 - if (bcIndex == 0) {  
101 - group.setBc1(bc);  
102 - bc.setGroup(group);  
103 - } else if (bcIndex == 1) {  
104 - group.setBc2(bc);  
105 - bc.setGroup(group);  
106 - }  
107 -};  
108 -  
109 -/**  
110 - * 设置原始路牌对象。  
111 - * @param lpObj 原始路牌对象  
112 - */  
113 -InternalLpObj.prototype.setLp = function(lpObj) {  
114 - this._$$_orign_lp_obj = lpObj;  
115 - var i;  
116 - var group;  
117 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
118 - group = this._$_groupBcArray[i];  
119 - if (group) {  
120 - group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象  
121 - }  
122 - }  
123 -};  
124 -  
125 -InternalLpObj.prototype.getLpNo = function() {  
126 - return this._$$_orign_lp_obj.lpNo;  
127 -};  
128 -InternalLpObj.prototype.getLpName = function() {  
129 - return this._$$_orign_lp_obj.lpName;  
130 -};  
131 -InternalLpObj.prototype.setBxFb5_2 = function(fb) {  
132 - this._$_bx_isfb_5_2 = fb;  
133 -};  
134 -InternalLpObj.prototype.isBxFb5_2 = function() {  
135 - return this._$_bx_isfb_5_2;  
136 -};  
137 -InternalLpObj.prototype.setBxLb = function(lb) {  
138 - this._$_bx_isLb = lb;  
139 -};  
140 -InternalLpObj.prototype.isBxLb = function() {  
141 - return this._$_bx_isLb;  
142 -};  
143 -  
144 -InternalLpObj.prototype.setBxFb = function(fb) {  
145 - this._$_bx_isfb = fb;  
146 -};  
147 -InternalLpObj.prototype.isBxFb = function() {  
148 - return this._$_bx_isfb;  
149 -};  
150 -  
151 -/**  
152 - * 设置路牌的班型描述(最终是设置班次的路牌名字)。  
153 - * @param desc 描述  
154 - */  
155 -InternalLpObj.prototype.setBxDesc = function(desc) {  
156 - // 最终原始路牌的名字  
157 - this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;  
158 - // 内部对象的班型描述  
159 - this._$_bx_desc = desc;  
160 -};  
161 -/**  
162 - * 获取版型描述  
163 - * @returns string  
164 - */  
165 -InternalLpObj.prototype.getBxDesc = function() {  
166 - return this._$_bx_desc;  
167 -};  
168 -  
169 -/**  
170 - * 设置纵向最小发车间隔时间。  
171 - * @param v  
172 - */  
173 -InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {  
174 - // 第一个路牌,都为0  
175 - this._$_minVerticalIntervalTime = v;  
176 -};  
177 -/**  
178 - * 获取纵向最小发车间隔时间。  
179 - * @returns {number|*}  
180 - */  
181 -InternalLpObj.prototype.getVerticalMinIntervalTime = function() {  
182 - return this._$_minVerticalIntervalTime;  
183 -};  
184 -  
185 -/**  
186 - * 设置纵向发车间隔。  
187 - * @param iQindex 圈index  
188 - * @param iBindex 班次index  
189 - * @param iTime 间隔时间  
190 - */  
191 -InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {  
192 - this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;  
193 -};  
194 -  
195 -/**  
196 - * 返回纵向发车间隔。  
197 - * @param iQindex 圈index  
198 - * @param iBindex 班次index  
199 - */  
200 -InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {  
201 - return this._$_aVerticalIntervalTime[iQindex][iBindex];  
202 -};  
203 -  
204 -//-------------------- 班次操作方法(查询,统计,删除) -----------------------//  
205 -  
206 -/**  
207 - * 返回总共班次数。  
208 - */  
209 -InternalLpObj.prototype.getBcCount = function() {  
210 - var i;  
211 - var group;  
212 - var bccount = 0;  
213 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
214 - group = this._$_groupBcArray[i];  
215 - if (group) {  
216 - if (group.getBc1()) {  
217 - bccount += 1;  
218 - }  
219 - if (group.getBc2()) {  
220 - bccount += 1;  
221 - }  
222 - }  
223 - }  
224 -  
225 - return bccount;  
226 -};  
227 -  
228 -/**  
229 - * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。  
230 - * @returns arrays (InternalBcObj)  
231 - */  
232 -InternalLpObj.prototype.getBcArray = function() {  
233 - var bcArray = [];  
234 - var i;  
235 - var group;  
236 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
237 - group = this._$_groupBcArray[i];  
238 - if (group) {  
239 - group.getBc1() ? bcArray.push(group.getBc1()) : "";  
240 - group.getBc2() ? bcArray.push(group.getBc2()) : "";  
241 - }  
242 - }  
243 -  
244 - return bcArray;  
245 -};  
246 -  
247 -/**  
248 - * 获取最小(最早)班次对象。  
249 - * @returns [{圈index},{班次index}]  
250 - */  
251 -InternalLpObj.prototype.getMinBcObjPosition = function() {  
252 - var i;  
253 - var bIndex = [];  
254 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
255 - if (this._$_groupBcArray[i].getBc1()) {  
256 - bIndex.push(i);  
257 - bIndex.push(0);  
258 - break;  
259 - }  
260 - if (this._$_groupBcArray[i].getBc2()) {  
261 - bIndex.push(i);  
262 - bIndex.push(1);  
263 - break;  
264 - }  
265 - }  
266 - return bIndex;  
267 -};  
268 -  
269 -/**  
270 - * 获取最大(最晚)班次对象。  
271 - * @returns [{圈index},{班次index}]  
272 - */  
273 -InternalLpObj.prototype.getMaxBcObjPosition = function() {  
274 - var i;  
275 - var bIndex = [];  
276 - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {  
277 - if (this._$_groupBcArray[i].getBc2()) {  
278 - bIndex.push(i);  
279 - bIndex.push(1);  
280 - break;  
281 - }  
282 - if (this._$_groupBcArray[i].getBc1()) {  
283 - bIndex.push(i);  
284 - bIndex.push(0);  
285 - break;  
286 - }  
287 - }  
288 - return bIndex;  
289 -};  
290 -  
291 -InternalLpObj.prototype.getMinBcObj = function() {  
292 - var i;  
293 - var bcObj;  
294 - for (i = 0; i < this._$_groupBcArray.length; i++) {  
295 - bcObj = this._$_groupBcArray[i].getBc1();  
296 - if (bcObj) {  
297 - break;  
298 - }  
299 - bcObj = this._$_groupBcArray[i].getBc2();  
300 - if (bcObj) {  
301 - break;  
302 - }  
303 - }  
304 - return bcObj;  
305 -};  
306 -InternalLpObj.prototype.getMaxBcObj = function() {  
307 - var i;  
308 - var bcObj;  
309 - for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {  
310 - bcObj = this._$_groupBcArray[i].getBc2();  
311 - if (bcObj) {  
312 - break;  
313 - }  
314 - bcObj = this._$_groupBcArray[i].getBc1();  
315 - if (bcObj) {  
316 - break;  
317 - }  
318 - }  
319 - return bcObj;  
320 -};  
321 -  
322 -/**  
323 - * 获取车次链信息。  
324 - * @param num 第几个车次链  
325 - * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}  
326 - */  
327 -InternalLpObj.prototype.fnGetBcChainInfo = function(num) {  
328 - // 计算总的车次链信息  
329 - var aChainInfo = [];  
330 - var oChainInfo;  
331 - var aBcIndex = this.getMinBcObjPosition();  
332 - var oBc;  
333 - var iQIndex;  
334 - var iBcIndex;  
335 - var i;  
336 - var bFlag;  
337 -  
338 - var iBcount = 0;  
339 -  
340 - if (aBcIndex.length == 2) {  
341 - iBcount = 1;  
342 - oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};  
343 - aChainInfo.push(oChainInfo);  
344 - bFlag = true;  
345 -  
346 - // 下一个班次的索引  
347 - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;  
348 - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;  
349 -  
350 - for (i = iQIndex; i < this._$_qCount; i++) {  
351 - while (iBcIndex <= 1) {  
352 - oBc = this.getBc(i, iBcIndex);  
353 - if (!oBc) {  
354 - if (bFlag) {  
355 - // 车次链结尾是这个班次的前一个班次  
356 - oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;  
357 - oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;  
358 - oChainInfo.bcount = iBcount;  
359 - }  
360 -  
361 - bFlag = false;  
362 - } else {  
363 - if (bFlag) {  
364 - iBcount ++;  
365 - oChainInfo.bcount = iBcount;  
366 - } else {  
367 - // 下一个车次链开始  
368 - iBcount = 1;  
369 - oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};  
370 - aChainInfo.push(oChainInfo);  
371 - bFlag = true;  
372 - }  
373 - }  
374 -  
375 -  
376 - iBcIndex ++;  
377 - }  
378 - iBcIndex = 0;  
379 - }  
380 -  
381 - }  
382 -  
383 - return aChainInfo[num];  
384 -};  
385 -  
386 -/**  
387 - * 获取车次链的个数。  
388 - * @returns int  
389 - */  
390 -InternalLpObj.prototype.fnGetBcChainCount = function() {  
391 - var iChainCount = 0;  
392 - var aBcIndex = this.getMinBcObjPosition();  
393 -  
394 - var oBc;  
395 - var iQIndex;  
396 - var iBcIndex;  
397 - var i;  
398 - var bFlag;  
399 -  
400 - if (aBcIndex.length == 2) {  
401 - iChainCount = 1;  
402 - bFlag = true;  
403 -  
404 - // 下一个班次的索引  
405 - iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;  
406 - iBcIndex = aBcIndex[1] == 0 ? 1 : 0;  
407 -  
408 - for (i = iQIndex; i < this._$_qCount; i++) {  
409 - while (iBcIndex <= 1) {  
410 - oBc = this.getBc(i, iBcIndex);  
411 - if (!oBc) {  
412 - bFlag = false;  
413 - } else {  
414 - if (bFlag) {  
415 -  
416 - } else {  
417 - iChainCount ++;  
418 - bFlag = true;  
419 - }  
420 - }  
421 -  
422 -  
423 - iBcIndex ++;  
424 - }  
425 - iBcIndex = 0;  
426 - }  
427 -  
428 - }  
429 -  
430 -  
431 - return iChainCount;  
432 -};  
433 -  
434 -/**  
435 - * 在具体位置移除班次。  
436 - * @param qIndex 第几圈  
437 - * @param bcIndex 第几个班次  
438 - */  
439 -InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {  
440 - var group = this._$_groupBcArray[qIndex];  
441 - if (bcIndex == 0) {  
442 - group.removeBc1();  
443 - } else if (bcIndex == 1) {  
444 - group.removeBc2();  
445 - }  
446 -};  
447 -  
448 -/**  
449 - * 使用指定时间匹配返回离之最近的第几圈第几个班次,  
450 - * 使用时间差的绝度值,比较,取最小的  
451 - * 如果有两个一样的时间差,取比fctime大的时间  
452 - * @param fctime moment 比较用时间  
453 - * @param groupArray 圈数组  
454 - * @param hasUp boolean 计算上行班次  
455 - * @param hasDown boolean 计算下行班次  
456 - * @returns [{第几圈},{第几个班次}]  
457 - */  
458 -InternalLpObj.prototype.getgetQBcIndexWithFcTimeFromGroupArray = function(  
459 - fctime, groupArray, hasUp, hasDown  
460 -) {  
461 - var i;  
462 - var timediff; // 时间差取绝对值  
463 - var qIndex;  
464 - var bcIndex;  
465 -  
466 - var group;  
467 - var bc1time;  
468 - var bc2time;  
469 -  
470 - var tempdiff;  
471 - for (i = 0; i < this._$_qCount; i++) {  
472 - group = groupArray[i];  
473 - if (group) {  
474 - if (group.getBc1() && hasUp) {  
475 - bc1time = group.getBc1().getFcTimeObj();  
476 - tempdiff = Math.abs(bc1time.diff(fctime));  
477 -  
478 - if (!timediff) {  
479 - timediff = Math.abs(tempdiff);  
480 - qIndex = i;  
481 - bcIndex = 0;  
482 - } else {  
483 - if (tempdiff < timediff) {  
484 - timediff = tempdiff;  
485 - qIndex = i;  
486 - bcIndex = 0;  
487 - } if (Math.abs(tempdiff) == timediff) {  
488 - if (bc1time.isBefore(fctime)) {  
489 - timediff = tempdiff;  
490 - qIndex = i;  
491 - bcIndex = 0;  
492 - }  
493 -  
494 - }  
495 - }  
496 - }  
497 -  
498 - if (group.getBc2() && hasDown) {  
499 - bc2time = group.getBc2().getFcTimeObj();  
500 - tempdiff = Math.abs(bc2time.diff(fctime));  
501 -  
502 - if (!timediff) {  
503 - timediff = Math.abs(tempdiff);  
504 - qIndex = i;  
505 - bcIndex = 1;  
506 - } else {  
507 - if (tempdiff < timediff) {  
508 - timediff = tempdiff;  
509 - qIndex = i;  
510 - bcIndex = 1;  
511 - } if (Math.abs(tempdiff) == timediff) {  
512 - if (bc2time.isBefore(fctime)) {  
513 - timediff = tempdiff;  
514 - qIndex = i;  
515 - bcIndex = 1;  
516 - }  
517 -  
518 - }  
519 - }  
520 - }  
521 - }  
522 - }  
523 -  
524 - var rst = [];  
525 - rst.push(qIndex);  
526 - rst.push(bcIndex);  
527 -  
528 - return rst;  
529 -};  
530 -  
531 -/**  
532 - * 使用指定时间匹配返回离之最近的第几圈第几个班次,  
533 - * 使用时间差的绝度值,比较,取最小的  
534 - * 如果有两个一样的时间差,取比fctime大的时间  
535 - * @param fctime moment 比较用时间  
536 - * @param hasUp boolean 计算上行班次  
537 - * @param hasDown boolean 计算下行班次  
538 - * @returns [{第几圈},{第几个班次}]  
539 - */  
540 -InternalLpObj.prototype.getQBcIndexWithFcTime = function(  
541 - fctime, hasUp, hasDown  
542 -) {  
543 - return this.getgetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);  
544 -};  
545 -  
546 -//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//  
547 -  
548 -/**  
549 - * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌  
550 - * 注意,之前有班次会删除后再创建。  
551 - * @param startTime 开始时间  
552 - * @param endTime 结束时间  
553 - * @param isUp 第一个班次是上行还是下行  
554 - * @param fromQ 从第几圈开始加入  
555 - * @param paramObj 参数对象  
556 - * @param factory 工厂对象  
557 - */  
558 -InternalLpObj.prototype.initDataFromTimeToTime = function(  
559 - startTime,  
560 - endTime,  
561 - isUp,  
562 - fromQ,  
563 - paramObj,  
564 - factory) {  
565 -  
566 - var bcData = []; // 班次数组  
567 - var bcObj;  
568 - var kssj = startTime;  
569 - var fcno = 1; // 发车顺序号  
570 - var bcCount = 1; // 班次数  
571 - do {  
572 - bcObj = factory.createBcObj(  
573 - this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象  
574 - bcData.push(bcObj);  
575 -  
576 - kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());  
577 - fcno ++;  
578 - bcCount ++;  
579 - isUp = !isUp;  
580 - } while(kssj.isBefore(endTime));  
581 - bcCount--;  
582 -  
583 - //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));  
584 - //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));  
585 - //console.log("endtime: " + endTime.format("HH:mm"));  
586 -  
587 - if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {  
588 - // 如果最后一个班次的到达时间超过结束时间,也要去除  
589 - bcData.splice(bcCount - 1, 1);  
590 - }  
591 -  
592 - this._initDataFromLbBcArray(bcData, fromQ);  
593 -  
594 -};  
595 -  
596 -/**  
597 - * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。  
598 - * @param bcArray 连班班次数组  
599 - * @param fromQ 从第几圈开始加入  
600 - */  
601 -InternalLpObj.prototype._initDataFromLbBcArray = function(  
602 - bcArray,  
603 - fromQ  
604 -) {  
605 - var _bc1Obj;  
606 - var _bc2Obj;  
607 - var _qObj;  
608 -  
609 - // 第一班次是上行还是下行  
610 - var isUp = bcArray[0].isUp();  
611 -  
612 - if (bcArray.length > 0 && fromQ < this._$_qCount) {  
613 - // 构造圈数  
614 - if (isUp != this._$_isUp) {  
615 - // 如果方向不一致,意味着第一个班次是半圈  
616 - // 加半圈,并加在bc2上  
617 - _bc2Obj = bcArray.slice(0, 1)[0];  
618 - _qObj = new InternalGroupObj(  
619 - this,  
620 - this._$_isUp,  
621 - undefined,  
622 - _bc2Obj  
623 - );  
624 - _bc2Obj.setGroup(_qObj);  
625 - this._$_groupBcArray[fromQ] = _qObj;  
626 -  
627 - bcArray.splice(0, 1);  
628 - fromQ ++;  
629 - }  
630 -  
631 - var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈  
632 - var qCount2 = bcArray.length % 2; // 最后是否有半圈  
633 -  
634 - while (fromQ < this._$_qCount) {  
635 - if (qCount1 > 0) {  
636 - _bc1Obj = bcArray.slice(0, 1)[0];  
637 - _bc2Obj = bcArray.slice(1, 2)[0];  
638 - _qObj = new InternalGroupObj(  
639 - this,  
640 - this._$_isUp,  
641 - _bc1Obj,  
642 - _bc2Obj  
643 - );  
644 - _bc1Obj.setGroup(_qObj);  
645 - _bc2Obj.setGroup(_qObj);  
646 - this._$_groupBcArray[fromQ] = _qObj;  
647 -  
648 - bcArray.splice(0, 2);  
649 - qCount1 --;  
650 - } else if (qCount2 > 0) {  
651 - // 加半圈,并加在bc1上  
652 - _bc1Obj = bcArray.slice(0, 1)[0];  
653 - _qObj = new InternalGroupObj(  
654 - this,  
655 - this._$_isUp,  
656 - _bc1Obj,  
657 - undefined  
658 - );  
659 - _bc1Obj.setGroup(_qObj);  
660 - this._$_groupBcArray[fromQ] = _qObj;  
661 -  
662 - bcArray.splice(0, 1);  
663 - qCount2 --;  
664 - } else {  
665 - break;  
666 - }  
667 -  
668 - fromQ ++;  
669 - }  
670 - }  
671 -};  
672 -  
673 -//-------------------------- 其他方法 ----------------------------//  
674 -  
675 -/**  
676 - * 从指定位置的班次开始,往后所有的班次修正发车时间  
677 - * @param groupIndex  
678 - * @param bcIndex  
679 - * @param time  
680 - */  
681 -InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {  
682 - var i;  
683 - var oCurBc;  
684 -  
685 - // 修正之前班次的停站时间  
686 - //oCurBc = this.getBc(  
687 - // bcIndex == 0 ? groupIndex - 1 : groupIndex,  
688 - // bcIndex == 1 ? 0 : 1  
689 - //);  
690 - //if (oCurBc) {  
691 - // oCurBc.setStopTime(oCurBc.getStopTime() + time);  
692 - //}  
693 -  
694 -  
695 - for (i = groupIndex; i < this._$_qCount; i++) {  
696 - if (bcIndex == 0) {  
697 - oCurBc = this.getBc(i, 0);  
698 - if (oCurBc) {  
699 - oCurBc.addMinuteToFcsj(time);  
700 - }  
701 - oCurBc = this.getBc(i, 1);  
702 - if (oCurBc) {  
703 - oCurBc.addMinuteToFcsj(time);  
704 - }  
705 -  
706 - } else {  
707 - oCurBc = this.getBc(i, 1);  
708 - if (oCurBc) {  
709 - oCurBc.addMinuteToFcsj(time);  
710 - }  
711 -  
712 - }  
713 -  
714 - bcIndex = 0;  
715 - }  
716 -};  
717 -  
718 -/**  
719 - * 在指定位置添加一个吃饭班次。  
720 - * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array  
721 - * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化  
722 - * @param groupIndex  
723 - * @param bcIndex  
724 - * @param factory  
725 - * @param paramObj  
726 - * @returns int 相差时间(吃饭时间距离和停站时间相差值)  
727 - */  
728 -InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {  
729 - var oPreBc;  
730 - var oEatBc;  
731 - var iBcModifyTime;  
732 - oPreBc = this.getBc( // 前一个邻接班次  
733 - bcIndex == 0 ? groupIndex - 1 : groupIndex,  
734 - bcIndex == 1 ? 0 : 1);  
735 - if (oPreBc) { // 存在前一个班次  
736 - oEatBc = factory.createBcObj(  
737 - this,  
738 - "cf",  
739 - !oPreBc.isUp(), // 和上一个班次方向相反  
740 - 1,  
741 - oPreBc.getArrTimeObj(), // 使用上一个班次的到达时间作为开始时间  
742 - paramObj  
743 - );  
744 -  
745 - //iBcModifyTime = oEatBc.getBcTime() - oPreBc.getStopTime(); // 后续班次要调整的时间  
746 -  
747 - // 修正之后的班次发车时间  
748 - // 注意:之后那个班次发车时间就是吃饭班次的到达时间  
749 - iBcModifyTime = oEatBc.getArrTimeObj().diff(this.getBc(groupIndex, bcIndex).getFcTimeObj(), "m");  
750 - this.fnAddMinuteToBcFcsj(groupIndex, bcIndex, iBcModifyTime);  
751 -  
752 - oPreBc.setStopTime(0);  
753 - this._$_other_bc_array.push(oEatBc);  
754 -  
755 - return iBcModifyTime;  
756 - } else {  
757 - return false;  
758 - }  
759 -  
760 -};  
761 -  
762 -  
763 -// TODO  
764 -  
765 -/**  
766 - *  
767 - *  
768 - */  
769 -InternalLpObj.prototype.calcuLpBx = function() {  
770 -  
771 -};  
772 -  
773 - 1 +/**
  2 + * 内部路牌对象。
  3 + * @constructor
  4 + */
  5 +var InternalLpObj = function(
  6 + orilpObj, // 原始路牌对象
  7 + qCount, // 总共多少圈
  8 + isUp // 圈是以上行开始还是下行开始
  9 +) {
  10 + // TODO:原始路牌对象(这个路牌是对接外部gantt图像,以后有机会改了)
  11 + this._$$_orign_lp_obj = orilpObj;
  12 +
  13 + this._$_isUp = isUp;
  14 +
  15 + // 路牌的圈数,注意每个路牌的圈数都是一致的,
  16 + // 但并不是每一圈都有值
  17 + // 第1圈从上标线开始
  18 + // 第0圈表示中标线的第一个班次组成的半圈
  19 + // 有多少圈根据最终迭代的结果来看
  20 + this._$_qCount = qCount;
  21 + // 保存的是 InternalGroupBcObj 对象
  22 + this._$_groupBcArray = new Array(qCount);
  23 +
  24 + var i;
  25 + for (i = 0; i < this._$_qCount; i++) {
  26 + this._$_groupBcArray[i] = new InternalGroupObj(
  27 + this, this._$_isUp, undefined, undefined);
  28 + }
  29 +
  30 + // 距离上一个路牌的最小发车间隔时间
  31 + // 用于纵向添加班次的时候使用
  32 + // 默认第一个路牌为0
  33 + this._$_minVerticalIntervalTime = 0;
  34 +
  35 + // 详细记录每圈每个方向上的发车间隔时间
  36 + // 第一维度表示圈数,第二维度表示第一个方向,第二个方向
  37 + // 第一个方向是否上行由 _$_isUp 决定
  38 + // 这里的间隔表示下一个路牌上的班次距离本路牌的班次发车时间间隔
  39 + // 如果当前是最后一个路牌,表示第一个路牌的下一圈同方向班次距离本班次的间隔
  40 + this._$_aVerticalIntervalTime = new Array(this._$_qCount);
  41 + var i;
  42 + for (i = 0; i < this._$_aVerticalIntervalTime.length; i++) {
  43 + this._$_aVerticalIntervalTime[i] = new Array(2);
  44 + }
  45 +
  46 + // 班型的相关变量
  47 + this._$_bx_isLb = false; // 是否连班
  48 + this._$_bx_isfb = false; // 是否分班
  49 + this._$_bx_isfb_5_2 = false; // 是否5休2分班
  50 + this._$_bx_desc; // 班型描述(默认为路牌编号)
  51 +
  52 + // 其他班次(进出场,例包,吃饭等),TODO:以后再拆
  53 + this._$_other_bc_array = [];
  54 +
  55 + // TODO:
  56 +
  57 +};
  58 +
  59 +//------------------- get/set 方法 -------------------//
  60 +
  61 +InternalLpObj.prototype.getOtherBcArray = function() {
  62 + return this._$_other_bc_array;
  63 +};
  64 +InternalLpObj.prototype.addOtherBcArray = function(ba) {
  65 + this._$_other_bc_array = this._$_other_bc_array.concat(ba);
  66 +};
  67 +
  68 +/**
  69 + * 获取圈
  70 + * @param qIndex 圈index
  71 + */
  72 +InternalLpObj.prototype.getGroup = function(qIndex) {
  73 + return this._$_groupBcArray[qIndex];
  74 +};
  75 +
  76 +/**
  77 + * 获取班次。
  78 + * @param qIndex 第几圈
  79 + * @param bcIndex 第几个班次
  80 + */
  81 +InternalLpObj.prototype.getBc = function(qIndex, bcIndex) {
  82 + var group = this._$_groupBcArray[qIndex];
  83 + var bc;
  84 + if (bcIndex == 0) {
  85 + bc = group.getBc1();
  86 + } else if (bcIndex == 1) {
  87 + bc = group.getBc2();
  88 + }
  89 + return bc;
  90 +};
  91 +
  92 +/**
  93 + * 在具体位置设置班次。
  94 + * @param qIndex 第几圈
  95 + * @param bcIndex 第几个班次
  96 + * @param bc 班次对象
  97 + */
  98 +InternalLpObj.prototype.setBc = function(qIndex, bcIndex, bc) {
  99 + var group = this._$_groupBcArray[qIndex];
  100 + if (bcIndex == 0) {
  101 + group.setBc1(bc);
  102 + bc.setGroup(group);
  103 + } else if (bcIndex == 1) {
  104 + group.setBc2(bc);
  105 + bc.setGroup(group);
  106 + }
  107 +};
  108 +
  109 +/**
  110 + * 设置原始路牌对象。
  111 + * @param lpObj 原始路牌对象
  112 + */
  113 +InternalLpObj.prototype.setLp = function(lpObj) {
  114 + this._$$_orign_lp_obj = lpObj;
  115 + var i;
  116 + var group;
  117 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  118 + group = this._$_groupBcArray[i];
  119 + if (group) {
  120 + group.setLp(this); // 圈和班次保存都是 InternalLpObj 对象
  121 + }
  122 + }
  123 +};
  124 +
  125 +InternalLpObj.prototype.getLpNo = function() {
  126 + return this._$$_orign_lp_obj.lpNo;
  127 +};
  128 +InternalLpObj.prototype.getLpName = function() {
  129 + return this._$$_orign_lp_obj.lpName;
  130 +};
  131 +InternalLpObj.prototype.setBxFb5_2 = function(fb) {
  132 + this._$_bx_isfb_5_2 = fb;
  133 +};
  134 +InternalLpObj.prototype.isBxFb5_2 = function() {
  135 + return this._$_bx_isfb_5_2;
  136 +};
  137 +InternalLpObj.prototype.setBxLb = function(lb) {
  138 + this._$_bx_isLb = lb;
  139 +};
  140 +InternalLpObj.prototype.isBxLb = function() {
  141 + return this._$_bx_isLb;
  142 +};
  143 +
  144 +InternalLpObj.prototype.setBxFb = function(fb) {
  145 + this._$_bx_isfb = fb;
  146 +};
  147 +InternalLpObj.prototype.isBxFb = function() {
  148 + return this._$_bx_isfb;
  149 +};
  150 +
  151 +/**
  152 + * 设置路牌的班型描述(最终是设置班次的路牌名字)。
  153 + * @param desc 描述
  154 + */
  155 +InternalLpObj.prototype.setBxDesc = function(desc) {
  156 + // 最终原始路牌的名字
  157 + this._$$_orign_lp_obj.lpName = desc + "_" + this._$$_orign_lp_obj.lpNo;
  158 + // 内部对象的班型描述
  159 + this._$_bx_desc = desc;
  160 +};
  161 +/**
  162 + * 获取版型描述
  163 + * @returns string
  164 + */
  165 +InternalLpObj.prototype.getBxDesc = function() {
  166 + return this._$_bx_desc;
  167 +};
  168 +
  169 +/**
  170 + * 设置纵向最小发车间隔时间。
  171 + * @param v
  172 + */
  173 +InternalLpObj.prototype.setVerticalMinIntervalTime = function(v) {
  174 + // 第一个路牌,都为0
  175 + this._$_minVerticalIntervalTime = v;
  176 +};
  177 +/**
  178 + * 获取纵向最小发车间隔时间。
  179 + * @returns {number|*}
  180 + */
  181 +InternalLpObj.prototype.getVerticalMinIntervalTime = function() {
  182 + return this._$_minVerticalIntervalTime;
  183 +};
  184 +
  185 +/**
  186 + * 设置纵向发车间隔。
  187 + * @param iQindex 圈index
  188 + * @param iBindex 班次index
  189 + * @param iTime 间隔时间
  190 + */
  191 +InternalLpObj.prototype.fnSetVerticalIntervalTime = function(iQindex, iBindex, iTime) {
  192 + this._$_aVerticalIntervalTime[iQindex][iBindex] = iTime;
  193 +};
  194 +
  195 +/**
  196 + * 返回纵向发车间隔。
  197 + * @param iQindex 圈index
  198 + * @param iBindex 班次index
  199 + */
  200 +InternalLpObj.prototype.fnGetVerticalIntervalTime = function(iQindex, iBindex) {
  201 + return this._$_aVerticalIntervalTime[iQindex][iBindex];
  202 +};
  203 +
  204 +//-------------------- 班次操作方法(查询,统计,删除) -----------------------//
  205 +
  206 +/**
  207 + * 返回总共班次数。
  208 + */
  209 +InternalLpObj.prototype.getBcCount = function() {
  210 + var i;
  211 + var group;
  212 + var bccount = 0;
  213 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  214 + group = this._$_groupBcArray[i];
  215 + if (group) {
  216 + if (group.getBc1()) {
  217 + bccount += 1;
  218 + }
  219 + if (group.getBc2()) {
  220 + bccount += 1;
  221 + }
  222 + }
  223 + }
  224 +
  225 + return bccount;
  226 +};
  227 +
  228 +/**
  229 + * 返回班次列表,过滤空的班次,将所有存在的班次连成连续的对象数组返回。
  230 + * @returns arrays (InternalBcObj)
  231 + */
  232 +InternalLpObj.prototype.getBcArray = function() {
  233 + var bcArray = [];
  234 + var i;
  235 + var group;
  236 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  237 + group = this._$_groupBcArray[i];
  238 + if (group) {
  239 + group.getBc1() ? bcArray.push(group.getBc1()) : "";
  240 + group.getBc2() ? bcArray.push(group.getBc2()) : "";
  241 + }
  242 + }
  243 +
  244 + return bcArray;
  245 +};
  246 +
  247 +/**
  248 + * 获取最小(最早)班次对象。
  249 + * @returns [{圈index},{班次index}]
  250 + */
  251 +InternalLpObj.prototype.getMinBcObjPosition = function() {
  252 + var i;
  253 + var bIndex = [];
  254 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  255 + if (this._$_groupBcArray[i].getBc1()) {
  256 + bIndex.push(i);
  257 + bIndex.push(0);
  258 + break;
  259 + }
  260 + if (this._$_groupBcArray[i].getBc2()) {
  261 + bIndex.push(i);
  262 + bIndex.push(1);
  263 + break;
  264 + }
  265 + }
  266 + return bIndex;
  267 +};
  268 +
  269 +/**
  270 + * 获取最大(最晚)班次对象。
  271 + * @returns [{圈index},{班次index}]
  272 + */
  273 +InternalLpObj.prototype.getMaxBcObjPosition = function() {
  274 + var i;
  275 + var bIndex = [];
  276 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  277 + if (this._$_groupBcArray[i].getBc2()) {
  278 + bIndex.push(i);
  279 + bIndex.push(1);
  280 + break;
  281 + }
  282 + if (this._$_groupBcArray[i].getBc1()) {
  283 + bIndex.push(i);
  284 + bIndex.push(0);
  285 + break;
  286 + }
  287 + }
  288 + return bIndex;
  289 +};
  290 +
  291 +InternalLpObj.prototype.getMinBcObj = function() {
  292 + var i;
  293 + var bcObj;
  294 + for (i = 0; i < this._$_groupBcArray.length; i++) {
  295 + bcObj = this._$_groupBcArray[i].getBc1();
  296 + if (bcObj) {
  297 + break;
  298 + }
  299 + bcObj = this._$_groupBcArray[i].getBc2();
  300 + if (bcObj) {
  301 + break;
  302 + }
  303 + }
  304 + return bcObj;
  305 +};
  306 +InternalLpObj.prototype.getMaxBcObj = function() {
  307 + var i;
  308 + var bcObj;
  309 + for (i = this._$_groupBcArray.length - 1; i >= 0; i--) {
  310 + bcObj = this._$_groupBcArray[i].getBc2();
  311 + if (bcObj) {
  312 + break;
  313 + }
  314 + bcObj = this._$_groupBcArray[i].getBc1();
  315 + if (bcObj) {
  316 + break;
  317 + }
  318 + }
  319 + return bcObj;
  320 +};
  321 +
  322 +/**
  323 + * 获取车次链信息。
  324 + * @param num 第几个车次链
  325 + * @returns object {s_q: {开始圈索引},s_b : {开始班次索引},e_q : {结束圈索引},e_b : {结束班次索引}, bcount : {班次数}}
  326 + */
  327 +InternalLpObj.prototype.fnGetBcChainInfo = function(num) {
  328 + // 计算总的车次链信息
  329 + var aChainInfo = [];
  330 + var oChainInfo;
  331 + var aBcIndex = this.getMinBcObjPosition();
  332 + var oBc;
  333 + var iQIndex;
  334 + var iBcIndex;
  335 + var i;
  336 + var bFlag;
  337 +
  338 + var iBcount = 0;
  339 +
  340 + if (aBcIndex.length == 2) {
  341 + iBcount = 1;
  342 + oChainInfo = {s_q : aBcIndex[0], s_b : aBcIndex[1], e_q : aBcIndex[0], e_b : aBcIndex[1], bcount: 1};
  343 + aChainInfo.push(oChainInfo);
  344 + bFlag = true;
  345 +
  346 + // 下一个班次的索引
  347 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  348 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  349 +
  350 + for (i = iQIndex; i < this._$_qCount; i++) {
  351 + while (iBcIndex <= 1) {
  352 + oBc = this.getBc(i, iBcIndex);
  353 + if (!oBc) {
  354 + if (bFlag) {
  355 + // 车次链结尾是这个班次的前一个班次
  356 + oChainInfo.e_q = iBcIndex == 0 ? i - 1 : i;
  357 + oChainInfo.e_b = iBcIndex == 0 ? 1 : 0;
  358 + oChainInfo.bcount = iBcount;
  359 + }
  360 +
  361 + bFlag = false;
  362 + } else {
  363 + if (bFlag) {
  364 + iBcount ++;
  365 + oChainInfo.bcount = iBcount;
  366 + } else {
  367 + // 下一个车次链开始
  368 + iBcount = 1;
  369 + oChainInfo = {s_q : i, s_b : iBcIndex, e_q : i, e_b : iBcIndex, bcount: 1};
  370 + aChainInfo.push(oChainInfo);
  371 + bFlag = true;
  372 + }
  373 + }
  374 +
  375 +
  376 + iBcIndex ++;
  377 + }
  378 + iBcIndex = 0;
  379 + }
  380 +
  381 + }
  382 +
  383 + return aChainInfo[num];
  384 +};
  385 +
  386 +/**
  387 + * 获取车次链的个数。
  388 + * @returns int
  389 + */
  390 +InternalLpObj.prototype.fnGetBcChainCount = function() {
  391 + var iChainCount = 0;
  392 + var aBcIndex = this.getMinBcObjPosition();
  393 +
  394 + var oBc;
  395 + var iQIndex;
  396 + var iBcIndex;
  397 + var i;
  398 + var bFlag;
  399 +
  400 + if (aBcIndex.length == 2) {
  401 + iChainCount = 1;
  402 + bFlag = true;
  403 +
  404 + // 下一个班次的索引
  405 + iQIndex = aBcIndex[1] == 0 ? aBcIndex[0] : aBcIndex[0] + 1;
  406 + iBcIndex = aBcIndex[1] == 0 ? 1 : 0;
  407 +
  408 + for (i = iQIndex; i < this._$_qCount; i++) {
  409 + while (iBcIndex <= 1) {
  410 + oBc = this.getBc(i, iBcIndex);
  411 + if (!oBc) {
  412 + bFlag = false;
  413 + } else {
  414 + if (bFlag) {
  415 +
  416 + } else {
  417 + iChainCount ++;
  418 + bFlag = true;
  419 + }
  420 + }
  421 +
  422 +
  423 + iBcIndex ++;
  424 + }
  425 + iBcIndex = 0;
  426 + }
  427 +
  428 + }
  429 +
  430 +
  431 + return iChainCount;
  432 +};
  433 +
  434 +/**
  435 + * 在具体位置移除班次。
  436 + * @param qIndex 第几圈
  437 + * @param bcIndex 第几个班次
  438 + */
  439 +InternalLpObj.prototype.removeBc = function(qIndex, bcIndex) {
  440 + var group = this._$_groupBcArray[qIndex];
  441 + if (bcIndex == 0) {
  442 + group.removeBc1();
  443 + } else if (bcIndex == 1) {
  444 + group.removeBc2();
  445 + }
  446 +};
  447 +
  448 +/**
  449 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  450 + * 使用时间差的绝度值,比较,取最小的
  451 + * 如果有两个一样的时间差,取比fctime大的时间
  452 + * @param fctime moment 比较用时间
  453 + * @param groupArray 圈数组
  454 + * @param hasUp boolean 计算上行班次
  455 + * @param hasDown boolean 计算下行班次
  456 + * @returns [{第几圈},{第几个班次}]
  457 + */
  458 +InternalLpObj.prototype.getgetQBcIndexWithFcTimeFromGroupArray = function(
  459 + fctime, groupArray, hasUp, hasDown
  460 +) {
  461 + var i;
  462 + var timediff; // 时间差取绝对值
  463 + var qIndex;
  464 + var bcIndex;
  465 +
  466 + var group;
  467 + var bc1time;
  468 + var bc2time;
  469 +
  470 + var tempdiff;
  471 + for (i = 0; i < this._$_qCount; i++) {
  472 + group = groupArray[i];
  473 + if (group) {
  474 + if (group.getBc1() && hasUp) {
  475 + bc1time = group.getBc1().getFcTimeObj();
  476 + tempdiff = Math.abs(bc1time.diff(fctime));
  477 +
  478 + if (!timediff) {
  479 + timediff = Math.abs(tempdiff);
  480 + qIndex = i;
  481 + bcIndex = 0;
  482 + } else {
  483 + if (tempdiff < timediff) {
  484 + timediff = tempdiff;
  485 + qIndex = i;
  486 + bcIndex = 0;
  487 + } if (Math.abs(tempdiff) == timediff) {
  488 + if (bc1time.isBefore(fctime)) {
  489 + timediff = tempdiff;
  490 + qIndex = i;
  491 + bcIndex = 0;
  492 + }
  493 +
  494 + }
  495 + }
  496 + }
  497 +
  498 + if (group.getBc2() && hasDown) {
  499 + bc2time = group.getBc2().getFcTimeObj();
  500 + tempdiff = Math.abs(bc2time.diff(fctime));
  501 +
  502 + if (!timediff) {
  503 + timediff = Math.abs(tempdiff);
  504 + qIndex = i;
  505 + bcIndex = 1;
  506 + } else {
  507 + if (tempdiff < timediff) {
  508 + timediff = tempdiff;
  509 + qIndex = i;
  510 + bcIndex = 1;
  511 + } if (Math.abs(tempdiff) == timediff) {
  512 + if (bc2time.isBefore(fctime)) {
  513 + timediff = tempdiff;
  514 + qIndex = i;
  515 + bcIndex = 1;
  516 + }
  517 +
  518 + }
  519 + }
  520 + }
  521 + }
  522 + }
  523 +
  524 + var rst = [];
  525 + rst.push(qIndex);
  526 + rst.push(bcIndex);
  527 +
  528 + return rst;
  529 +};
  530 +
  531 +/**
  532 + * 使用指定时间匹配返回离之最近的第几圈第几个班次,
  533 + * 使用时间差的绝度值,比较,取最小的
  534 + * 如果有两个一样的时间差,取比fctime大的时间
  535 + * @param fctime moment 比较用时间
  536 + * @param hasUp boolean 计算上行班次
  537 + * @param hasDown boolean 计算下行班次
  538 + * @returns [{第几圈},{第几个班次}]
  539 + */
  540 +InternalLpObj.prototype.getQBcIndexWithFcTime = function(
  541 + fctime, hasUp, hasDown
  542 +) {
  543 + return this.getgetQBcIndexWithFcTimeFromGroupArray(fctime, this._$_groupBcArray, hasUp, hasDown);
  544 +};
  545 +
  546 +//---------------------- 内部数据初始化方法(不同于构造函数)---------------------//
  547 +
  548 +/**
  549 + * 从指定开始时间到结束时间创建不间断班次(连班),并初始化路牌
  550 + * 注意,之前有班次会删除后再创建。
  551 + * @param startTime 开始时间
  552 + * @param endTime 结束时间
  553 + * @param isUp 第一个班次是上行还是下行
  554 + * @param fromQ 从第几圈开始加入
  555 + * @param paramObj 参数对象
  556 + * @param factory 工厂对象
  557 + */
  558 +InternalLpObj.prototype.initDataFromTimeToTime = function(
  559 + startTime,
  560 + endTime,
  561 + isUp,
  562 + fromQ,
  563 + paramObj,
  564 + factory) {
  565 +
  566 + var bcData = []; // 班次数组
  567 + var bcObj;
  568 + var kssj = startTime;
  569 + var fcno = 1; // 发车顺序号
  570 + var bcCount = 1; // 班次数
  571 + do {
  572 + bcObj = factory.createBcObj(
  573 + this, "normal", isUp, fcno, kssj, paramObj); // this就是所属路牌对象
  574 + bcData.push(bcObj);
  575 +
  576 + kssj = paramObj.addMinute(kssj, bcObj.getBcTime() + bcObj.getStopTime());
  577 + fcno ++;
  578 + bcCount ++;
  579 + isUp = !isUp;
  580 + } while(kssj.isBefore(endTime));
  581 + bcCount--;
  582 +
  583 + //console.log("last -1;" + bcData[bcCount -2].getFcTimeObj().format("HH:mm"));
  584 + //console.log("last;" + bcData[bcCount -1].getFcTimeObj().format("HH:mm"));
  585 + //console.log("endtime: " + endTime.format("HH:mm"));
  586 +
  587 + //if (bcCount > 0 && bcData[bcCount - 1].getArrTimeObj().isAfter(endTime)) {
  588 + // // 如果最后一个班次的到达时间超过结束时间,也要去除
  589 + // bcData.splice(bcCount - 1, 1);
  590 + //}
  591 +
  592 + this._initDataFromLbBcArray(bcData, fromQ);
  593 +
  594 +};
  595 +
  596 +/**
  597 + * 使用连班的班次数组初始化路牌(相应的圈会被覆盖)。
  598 + * @param bcArray 连班班次数组
  599 + * @param fromQ 从第几圈开始加入
  600 + */
  601 +InternalLpObj.prototype._initDataFromLbBcArray = function(
  602 + bcArray,
  603 + fromQ
  604 +) {
  605 + var _bc1Obj;
  606 + var _bc2Obj;
  607 + var _qObj;
  608 +
  609 + // 第一班次是上行还是下行
  610 + var isUp = bcArray[0].isUp();
  611 +
  612 + if (bcArray.length > 0 && fromQ < this._$_qCount) {
  613 + // 构造圈数
  614 + if (isUp != this._$_isUp) {
  615 + // 如果方向不一致,意味着第一个班次是半圈
  616 + // 加半圈,并加在bc2上
  617 + _bc2Obj = bcArray.slice(0, 1)[0];
  618 + _qObj = new InternalGroupObj(
  619 + this,
  620 + this._$_isUp,
  621 + undefined,
  622 + _bc2Obj
  623 + );
  624 + _bc2Obj.setGroup(_qObj);
  625 + this._$_groupBcArray[fromQ] = _qObj;
  626 +
  627 + bcArray.splice(0, 1);
  628 + fromQ ++;
  629 + }
  630 +
  631 + var qCount1 = Math.floor(bcArray.length / 2); // 需要添加多少圈
  632 + var qCount2 = bcArray.length % 2; // 最后是否有半圈
  633 +
  634 + while (fromQ < this._$_qCount) {
  635 + if (qCount1 > 0) {
  636 + _bc1Obj = bcArray.slice(0, 1)[0];
  637 + _bc2Obj = bcArray.slice(1, 2)[0];
  638 + _qObj = new InternalGroupObj(
  639 + this,
  640 + this._$_isUp,
  641 + _bc1Obj,
  642 + _bc2Obj
  643 + );
  644 + _bc1Obj.setGroup(_qObj);
  645 + _bc2Obj.setGroup(_qObj);
  646 + this._$_groupBcArray[fromQ] = _qObj;
  647 +
  648 + bcArray.splice(0, 2);
  649 + qCount1 --;
  650 + } else if (qCount2 > 0) {
  651 + // 加半圈,并加在bc1上
  652 + _bc1Obj = bcArray.slice(0, 1)[0];
  653 + _qObj = new InternalGroupObj(
  654 + this,
  655 + this._$_isUp,
  656 + _bc1Obj,
  657 + undefined
  658 + );
  659 + _bc1Obj.setGroup(_qObj);
  660 + this._$_groupBcArray[fromQ] = _qObj;
  661 +
  662 + bcArray.splice(0, 1);
  663 + qCount2 --;
  664 + } else {
  665 + break;
  666 + }
  667 +
  668 + fromQ ++;
  669 + }
  670 + }
  671 +};
  672 +
  673 +//-------------------------- 其他方法 ----------------------------//
  674 +
  675 +/**
  676 + * 从指定位置的班次开始,往后所有的班次修正发车时间
  677 + * @param groupIndex
  678 + * @param bcIndex
  679 + * @param time
  680 + */
  681 +InternalLpObj.prototype.fnAddMinuteToBcFcsj = function(groupIndex, bcIndex, time) {
  682 + var i;
  683 + var oCurBc;
  684 +
  685 + // 修正之前班次的停站时间
  686 + //oCurBc = this.getBc(
  687 + // bcIndex == 0 ? groupIndex - 1 : groupIndex,
  688 + // bcIndex == 1 ? 0 : 1
  689 + //);
  690 + //if (oCurBc) {
  691 + // oCurBc.setStopTime(oCurBc.getStopTime() + time);
  692 + //}
  693 +
  694 +
  695 + for (i = groupIndex; i < this._$_qCount; i++) {
  696 + if (bcIndex == 0) {
  697 + oCurBc = this.getBc(i, 0);
  698 + if (oCurBc) {
  699 + oCurBc.addMinuteToFcsj(time);
  700 + }
  701 + oCurBc = this.getBc(i, 1);
  702 + if (oCurBc) {
  703 + oCurBc.addMinuteToFcsj(time);
  704 + }
  705 +
  706 + } else {
  707 + oCurBc = this.getBc(i, 1);
  708 + if (oCurBc) {
  709 + oCurBc.addMinuteToFcsj(time);
  710 + }
  711 +
  712 + }
  713 +
  714 + bcIndex = 0;
  715 + }
  716 +};
  717 +
  718 +/**
  719 + * 在指定位置添加一个吃饭班次。
  720 + * 注1:吃饭班次不是普通班次,不记录进圈,记录进_$_other_bc_array
  721 + * 注2:添加吃饭班次时,会修改之前班次的停战时间,所以导致之后的班次的停战都会发生变化
  722 + * @param groupIndex
  723 + * @param bcIndex
  724 + * @param factory
  725 + * @param paramObj
  726 + * @returns int 相差时间(吃饭时间距离和停站时间相差值)
  727 + */
  728 +InternalLpObj.prototype.fnAddEatBc = function(groupIndex, bcIndex, factory, paramObj) {
  729 + var oPreBc;
  730 + var oEatBc;
  731 + var iBcModifyTime;
  732 + oPreBc = this.getBc( // 前一个邻接班次
  733 + bcIndex == 0 ? groupIndex - 1 : groupIndex,
  734 + bcIndex == 1 ? 0 : 1);
  735 + if (oPreBc) { // 存在前一个班次
  736 + oEatBc = factory.createBcObj(
  737 + this,
  738 + "cf",
  739 + !oPreBc.isUp(), // 和上一个班次方向相反
  740 + 1,
  741 + 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 +