plan.drl
16.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
package com.bsth.service.schedule.plan;
import org.joda.time.*;
import java.util.*;
import com.bsth.service.schedule.rules.plan.PlanCalcuParam_input;
import com.bsth.service.schedule.rules.plan.PlanResult;
import com.bsth.repository.schedule.TTInfoDetailRepository;
import com.bsth.repository.schedule.CarConfigInfoRepository;
import com.bsth.repository.schedule.EmployeeConfigInfoRepository;
import com.bsth.repository.LineRepository;
import com.bsth.repository.BusinessRepository;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResult_output;
import com.bsth.service.schedule.rules.shiftloop.ScheduleResults_output;
import com.bsth.service.schedule.rules.ttinfo.TTInfoResult_output;
import com.bsth.service.schedule.rules.ttinfo.TTInfoResults_output;
import com.bsth.entity.Line;
import com.bsth.entity.Business;
import com.bsth.entity.schedule.CarConfigInfo;
import com.bsth.entity.schedule.EmployeeConfigInfo;
import com.bsth.entity.schedule.TTInfo;
import com.bsth.entity.schedule.TTInfoDetail;
import com.bsth.entity.schedule.SchedulePlanInfo;
import org.slf4j.Logger
import org.joda.time.format.DateTimeFormat
import org.apache.commons.lang3.StringUtils;
// 全局日志类(一般使用调用此规则的service类)
global Logger log;
global TTInfoDetailRepository tTInfoDetailRepository;
global CarConfigInfoRepository carConfigInfoRepository;
global EmployeeConfigInfoRepository employeeConfigInfoRepository;
global LineRepository lineRepository;
global BusinessRepository businessRepository;
// 输出
global PlanResult planResult;
function Map xlidParams(String xlid) {
Map param = new HashMap();
param.put("xl.id_eq", Integer.valueOf(xlid));
return param;
}
function List ecList(EmployeeConfigInfoRepository repo, String ecids) {
List<String> ids = Arrays.asList(ecids.split("-"));
List rst = new ArrayList();
for (int i = 0; i < ids.size(); i++) {
rst.add(repo.findOne(Long.parseLong(ids.get(i))));
}
return rst;
}
function LocalTime fcsjTime(String fcsj) {
if ("NULL".equals(fcsj)) {
return null;
}
return LocalTime.parse(fcsj, DateTimeFormat.forPattern("HH:mm"));
}
function String ttInfoId_sd(Map map, DateTime sd) {
TTInfoResult_output ttInfoResult_output = (TTInfoResult_output) map.get(sd);
return ttInfoResult_output.getTtInfoId();
}
function Map gsMap(List gses) {
Map gsMap = new HashMap();
for (int i = 0; i < gses.size(); i++) {
Business gs = (Business) gses.get(i);
if (StringUtils.isNotEmpty(gs.getBusinessCode())) {
if ("88".equals(gs.getUpCode())) { // 浦东公交
gsMap.put(gs.getBusinessCode(), gs);
}
if (gs.getBusinessCode().equals(gs.getUpCode())) { // 闵行,青浦
gsMap.put(gs.getBusinessCode(), gs);
}
}
}
return gsMap;
}
function Map fgsMap(List gses) {
// 这里简单将 businessCode和upCode合并
Map fgsMap = new HashMap();
for (int i = 0; i < gses.size(); i++) {
Business gs = (Business) gses.get(i);
if (StringUtils.isNotEmpty(gs.getBusinessCode()) && StringUtils.isNotEmpty(gs.getUpCode())) {
fgsMap.put(gs.getUpCode() + "_" + gs.getBusinessCode(), gs);
}
}
return fgsMap;
}
/*
规则说明:
根据循环规则输出,时刻表选择规则输出,组合计算排班明细
*/
//-------------------- 第一阶段、计算迭代数据 -----------------//
declare Loop_result
xlId: String // 线路id
ruleLoop: List // 每天分配的规则 List<ScheduleResult_output>
ttInfoMapLoop_temp: Map // 每天分配的时刻表 Map<DataTime, Collection<TTInfoResult_output>>
ttInfoMapLoop: Map // 每天分配的时刻表 Map<DataTime, TTInfoResult_output>
ttInfoMap: Map // 总共用到的时刻表 Map<id, TTInfoResult_output>
end
rule "calcu_step1_Loop_result"
salience 1000
when
$param: PlanCalcuParam_input($xlId: xlId)
then
Loop_result loop_result = new Loop_result();
loop_result.setXlId($xlId);
loop_result.setRuleLoop($param.getScheduleResults_output().getResults());
loop_result.setTtInfoMapLoop(new HashMap());
loop_result.setTtInfoMap(new HashMap());
com.google.common.collect.Multimap ttInfoMap_temp =
(com.google.common.collect.Multimap)
$param.getTtInfoResults_output().getResults().get(
String.valueOf($xlId));
loop_result.setTtInfoMapLoop_temp(ttInfoMap_temp.asMap());
insert(loop_result);
// log.info("calcu_step1_Loop_result");
end
rule "calcu_step2_loop_result"
salience 1000
no-loop
when
$param: PlanCalcuParam_input($xlId: xlId)
$lr: Loop_result(xlId == $xlId)
$sd: DateTime() from $lr.ttInfoMapLoop_temp.keySet()
then
// 当天时刻表只取第一张 TODO:
Collection col = (Collection) $lr.getTtInfoMapLoop_temp().get($sd);
Iterator iter = col.iterator();
TTInfoResult_output ttInfo_result = (TTInfoResult_output) iter.next();
$lr.getTtInfoMapLoop().put($sd, ttInfo_result);
// 总共使用的时刻表
$lr.getTtInfoMap().put(ttInfo_result.getTtInfoId(), ttInfo_result);
update($lr);
// log.info("calcu_step2_Loop_result");
end
//-------------------- 第二阶段、将时刻表班次,车辆配置,人员配置信息载入 -----------------//
//--------------- 车辆配置信息载入 -------------//
declare CarConfig_Wraps
xlId: String // 线路Id
ccMap: Map // 车辆配置Map Map<id, CarConfigInfo>
end
rule "calcu_CarConfig_Wraps"
salience 800
when
$lr: Loop_result($xlId: xlId)
then
List carConfigInfos = carConfigInfoRepository.findByXlId(Integer.parseInt($xlId));
CarConfig_Wraps carConfig_wraps = new CarConfig_Wraps();
carConfig_wraps.setXlId($xlId);
carConfig_wraps.setCcMap(new HashMap());
for (int i = 0; i < carConfigInfos.size(); i++) {
CarConfigInfo carConfigInfo = (CarConfigInfo) carConfigInfos.get(i);
carConfig_wraps.getCcMap().put(carConfigInfo.getId().toString(), carConfigInfo);
}
insert(carConfig_wraps);
log.info("calcu_CarConfig_Wrap");
end
//--------------- 人员配置信息载入 --------------//
declare EmployeeConfig_Wraps
xlId: String // 线路Id
ecMap: Map // 人员配置Map Map<id, EmployeeConfigInfo>
end
rule "calcu_EmployeeConfig_Wraps"
salience 800
when
$lr: Loop_result($xlId: xlId)
then
List employeeConfigInfos = employeeConfigInfoRepository.findByXlId(Integer.parseInt($xlId));
EmployeeConfig_Wraps employeeConfig_wraps = new EmployeeConfig_Wraps();
employeeConfig_wraps.setXlId($xlId);
employeeConfig_wraps.setEcMap(new HashMap());
for (int i = 0; i < employeeConfigInfos.size(); i++) {
EmployeeConfigInfo employeeConfigInfo = (EmployeeConfigInfo) employeeConfigInfos.get(i);
employeeConfig_wraps.getEcMap().put(employeeConfigInfo.getId().toString(), employeeConfigInfo);
}
insert(employeeConfig_wraps);
log.info("calcu_EmployeeConfig_Wrap");
end
//----------------- 时刻表班次信息载入 -----------------//
declare TTInfo_gid_stat
xlId: String // 线路id(cast字符串-方便比较)
ttInfoId: String // 时刻表id(cast字符串-方便比较)
gid: String // 路牌id(cast字符串-方便比较)
maxFcno: Integer // 最大发车顺序号
fbTime: LocalTime // 分班时间
end
rule "calcu_TTInfo_gid_stat"
salience 800
when
$lr: Loop_result($xlId: xlId)
$ttInfoId: String() from $lr.getTtInfoMap().keySet()
$gids: List() from accumulate ($ttd: TTInfoDetail() from tTInfoDetailRepository.findByTtinfoId(Long.parseLong($ttInfoId)), gidscount($ttd))
$gid: String() from $gids
$fbtime_str: String() from accumulate ($ttd: TTInfoDetail(lp.id.toString() == $gid) from tTInfoDetailRepository.findByTtinfoId(Long.parseLong($ttInfoId)), gidfbtime($ttd))
$maxfcno: Double() from accumulate ($ttd: TTInfoDetail(lp.id.toString() == $gid) from tTInfoDetailRepository.findByTtinfoId(Long.parseLong($ttInfoId)), max($ttd.getFcno()))
then
TTInfo_gid_stat ttInfo_gid_stat = new TTInfo_gid_stat();
ttInfo_gid_stat.setXlId($xlId);
ttInfo_gid_stat.setTtInfoId($ttInfoId);
ttInfo_gid_stat.setGid($gid);
ttInfo_gid_stat.setMaxFcno($maxfcno.intValue());
ttInfo_gid_stat.setFbTime(fcsjTime($fbtime_str));
insert(ttInfo_gid_stat);
// log.info("xlid={},ttid={},gid={},maxfcno={},fbtime={}",
// $xlId, $ttInfoId, $gid, ttInfo_gid_stat.getMaxFcno(), ttInfo_gid_stat.getFbTime());
end
declare TTInfoDetail_Wrap
isFirstBc: Boolean = false // 是否是当前路牌的第一个班次
isLastBc: Boolean = false // 是否是当前路牌的最后一个班次
isFb: Boolean = false // 是否分班
self: TTInfoDetail // 原始数据
end
declare TTInfoDetail_Wraps
xlId: String // 线路id(cast字符串-方便比较)
ttInfoId: String // 时刻表id(cast字符串-方便比较)
detailsMap: Map // 明细Map,Map<路牌id, List<TTInfoDetail_Wrap>>
end
rule "calcu_TTInfoDetail_Wraps"
salience 700
when
$lr: Loop_result($xlId: xlId)
$ttInfoId: String() from $lr.getTtInfoMap().keySet()
$ttInfoStatList: List(size > 0) from collect (TTInfo_gid_stat(ttInfoId == $ttInfoId))
then
TTInfoDetail_Wraps ttInfoDetail_wraps = new TTInfoDetail_Wraps();
ttInfoDetail_wraps.setXlId($xlId);
ttInfoDetail_wraps.setTtInfoId($ttInfoId);
ttInfoDetail_wraps.setDetailsMap(new HashMap());
// 将list的形式变成 Map<路牌id, TTInfo_gid_stat>
Map statMap = new HashMap();
for (int i = 0; i < $ttInfoStatList.size(); i++) {
TTInfo_gid_stat ttInfo_gid_stat = (TTInfo_gid_stat) $ttInfoStatList.get(i);
statMap.put(ttInfo_gid_stat.getGid(), ttInfo_gid_stat);
}
// 迭代ttinfodetail,拼装 TTInfoDetail_Wraps
List detaillist = tTInfoDetailRepository.findByTtinfoId(Long.parseLong($ttInfoId));
for (int j = 0; j < detaillist.size(); j++) {
TTInfoDetail ttInfoDetail = (TTInfoDetail) detaillist.get(j);
String gid = String.valueOf(ttInfoDetail.getLp().getId());
if (ttInfoDetail_wraps.getDetailsMap().get(gid) == null) {
ttInfoDetail_wraps.getDetailsMap().put(gid, new ArrayList());
}
// 获取stat
TTInfo_gid_stat ttInfo_gid_stat = (TTInfo_gid_stat) statMap.get(gid);
TTInfoDetail_Wrap ttInfoDetail_wrap = new TTInfoDetail_Wrap();
ttInfoDetail_wrap.setIsFirstBc(1 == ttInfoDetail.getFcno());
ttInfoDetail_wrap.setIsLastBc(ttInfo_gid_stat.getMaxFcno() == ttInfoDetail.getFcno());
LocalTime fcsj = fcsjTime(ttInfoDetail.getFcsj());
LocalTime fbsj = ttInfo_gid_stat.getFbTime();
ttInfoDetail_wrap.setIsFb(fbsj == null ? false : (fcsj.isEqual(fbsj) || fcsj.isAfter(fbsj)));
ttInfoDetail_wrap.setSelf(ttInfoDetail);
((List) ttInfoDetail_wraps.getDetailsMap().get(gid)).add(ttInfoDetail_wrap);
}
insert(ttInfoDetail_wraps);
log.info("xlid={}, ttinfoid={}, lpstatCount={}, detailLpCount={}",
$xlId, $ttInfoId, $ttInfoStatList.size(), ttInfoDetail_wraps.getDetailsMap().keySet().size());
end
declare TTInfoDetail_Wraps_map
xlId: String // 线路id(cast字符串-方便比较)
wrapsMap: Map // 明细Map,Map<时刻表Id, TTInfoDetail_Wraps>
end
rule "calcu_TTInfoDetail_Wraps_toMap"
salience 600
when
$lr: Loop_result($xlId: xlId)
$wrapsList: List(size > 0) from collect (TTInfoDetail_Wraps(xlId == $xlId))
then
// 转换成Map
TTInfoDetail_Wraps_map all = new TTInfoDetail_Wraps_map();
all.setXlId($xlId);
all.setWrapsMap(new HashMap());
for (int i = 0; i < $wrapsList.size(); i++) {
TTInfoDetail_Wraps ttInfoDetail_wraps = (TTInfoDetail_Wraps) $wrapsList.get(i);
all.getWrapsMap().put(ttInfoDetail_wraps.getTtInfoId(), ttInfoDetail_wraps);
}
insert(all);
end
//-------------------- 第三阶段、合并计算SchedulePlanInfo -----------------//
rule "Calcu_SchedulePlanInfo"
salience 500
when
$param: PlanCalcuParam_input($xlId: xlId)
$lr: Loop_result(xlId == $xlId)
$ccs: CarConfig_Wraps(xlId == $xlId)
$ecs: EmployeeConfig_Wraps(xlId == $xlId)
$tts: TTInfoDetail_Wraps_map(xlId == $xlId)
then
// 线路
Line xl = lineRepository.findOne(Integer.parseInt($xlId));
// 查找公司
List gses = (List) businessRepository.findAll();
// 构造公司代码对应map
Map gsMap = gsMap(gses);
// 构造分公司对应的map
Map fgsMap = fgsMap(gses);
for (int i = 0; i < $lr.getRuleLoop().size(); i++) {
ScheduleResult_output sro = (ScheduleResult_output) $lr.getRuleLoop().get(i);
// 日期
DateTime sd = sro.getSd();
// 路牌
String gid = sro.getGuideboardId();
// 车辆配置
CarConfigInfo carConfigInfo = (CarConfigInfo) $ccs.getCcMap().get(sro.getCarConfigId());
// 人员配置
List eclist = ecList(employeeConfigInfoRepository, sro.getEmployeeConfigId());
// 时刻表id
String ttInfoId = ttInfoId_sd($lr.getTtInfoMapLoop(), sd);
TTInfoDetail_Wraps ttInfoDetail_wraps = (TTInfoDetail_Wraps) $tts.getWrapsMap().get(ttInfoId);
if (ttInfoDetail_wraps == null) {
// 时刻表为空,直接跳过
// 如1118路,周末不开,此是时刻表指定一个空表
// TODO:这个以后要改的,选时刻表的规则要修正,没有默认的时刻表
continue;
}
List detaillist = (List) ttInfoDetail_wraps.getDetailsMap().get(gid);
if (detaillist == null) {
// 这里翻到的路牌时刻表里可能没有,
// 因为没有考虑翻班格式(就是做几休几)
// 所有翻班格式全由时刻表决定,即时刻表有的路牌就做,没有不做
continue;
}
for (int j = 0; j < detaillist.size(); j++) {
TTInfoDetail_Wrap wrap = (TTInfoDetail_Wrap) detaillist.get(j);
SchedulePlanInfo schedulePlanInfo = new SchedulePlanInfo(
xl,
sro,
wrap.getSelf(),
wrap.getIsFb(),
carConfigInfo,
eclist,
$param.getSchedulePlan(),
wrap.getIsFirstBc(),
wrap.getIsLastBc()
);
// 获取公司,分公司信息
String gsbm = xl.getCompany();
String fgsbm = xl.getBrancheCompany();
Business gs = null;
Business fgs = null;
if (StringUtils.isNotEmpty(gsbm)) {
gs = (Business) gsMap.get(gsbm);
}
if (StringUtils.isNotEmpty(gsbm) && StringUtils.isNotEmpty(fgsbm)) {
fgs = (Business) fgsMap.get(gsbm + "_" + fgsbm);
}
if (gs != null) {
schedulePlanInfo.setGsBm(gs.getBusinessCode());
schedulePlanInfo.setGsName(gs.getBusinessName());
}
if (fgs != null) {
schedulePlanInfo.setFgsBm(fgs.getBusinessCode());
schedulePlanInfo.setFgsName(fgs.getBusinessName());
}
// 操作人,操作时间
schedulePlanInfo.setCreateBy($param.getSchedulePlan().getCreateBy());
schedulePlanInfo.setCreateDate($param.getSchedulePlan().getCreateDate());
schedulePlanInfo.setUpdateBy($param.getSchedulePlan().getUpdateBy());
schedulePlanInfo.setUpdateDate($param.getSchedulePlan().getUpdateDate());
// result 输出
planResult.getSchedulePlanInfos().add(schedulePlanInfo);
}
}
log.info("xlid={} plan ok!", $xlId);
end