Commit 14e3a3109cbab5f34c03c43705043d809698dbe8

Authored by 徐烜
1 parent 3e48f68c

时刻表v2.7.15

1、添加StrategyUtils控制类,控制策略的动态添加删除
2、修改paramadd.html模版,允许重新生成时刻表时,动态选择策略,下拉选择的策略名就是策略函数名,也是内部变量名
3、添加4组发车间隔策略供选择,以下4组
   AdjustTripS1.js 就是之前的第一种调整策略
   AdjustTripS2.js 严格匹配是否可以调整发车间隔(这个速度很慢,暂时不用)
   AdjustTripS3.js 相对于S1严格点,就是如果超出间隔范围,+/-1分钟
   AdjustTripS4.js 使用两阶段平衡,第一阶段使用S1方式平衡,第二阶段找出吃饭时间,周转时间不足的班次,向后拉停站时间补足

Too many changes to show.

To preserve performance only 6 of 13 files are displayed.

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