Commit 7f799a68a88e95206eeded82336b1be0ebbacef1
1 parent
a2d14a12
Update
Showing
10 changed files
with
267 additions
and
9 deletions
src/main/java/com/bsth/service/schedule/impl/SchedulePlanServiceImpl.java
| @@ -21,6 +21,9 @@ import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input; | @@ -21,6 +21,9 @@ import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input; | ||
| 21 | import com.bsth.service.schedule.rules.ttinfo.*; | 21 | import com.bsth.service.schedule.rules.ttinfo.*; |
| 22 | import com.bsth.service.schedule.rules.ttinfo2.CalcuParam; | 22 | import com.bsth.service.schedule.rules.ttinfo2.CalcuParam; |
| 23 | import com.bsth.service.schedule.rules.ttinfo2.Result; | 23 | import com.bsth.service.schedule.rules.ttinfo2.Result; |
| 24 | +import com.bsth.service.schedule.rules.validate.ValidateParam; | ||
| 25 | +import com.bsth.service.schedule.rules.validate.ValidateResults_output; | ||
| 26 | +import org.apache.commons.lang3.StringUtils; | ||
| 24 | import org.joda.time.DateTime; | 27 | import org.joda.time.DateTime; |
| 25 | import org.kie.api.KieBase; | 28 | import org.kie.api.KieBase; |
| 26 | import org.kie.api.runtime.KieSession; | 29 | import org.kie.api.runtime.KieSession; |
| @@ -321,6 +324,59 @@ public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> im | @@ -321,6 +324,59 @@ public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> im | ||
| 321 | 324 | ||
| 322 | } | 325 | } |
| 323 | 326 | ||
| 327 | + /** | ||
| 328 | + * 验证排班结果。 | ||
| 329 | + * @param planResult | ||
| 330 | + * @param schedulePlan | ||
| 331 | + */ | ||
| 332 | + public void validPlanResult(PlanResult planResult, SchedulePlan schedulePlan) { | ||
| 333 | + // 1-1、构造drools规则输入数据,输出数据 | ||
| 334 | + ValidateParam validateParam = new ValidateParam( | ||
| 335 | + new DateTime(schedulePlan.getScheduleFromTime()), | ||
| 336 | + new DateTime(schedulePlan.getScheduleToTime()) | ||
| 337 | + ); | ||
| 338 | + // 规则输出数据 | ||
| 339 | + ValidateResults_output result = new ValidateResults_output(); | ||
| 340 | + | ||
| 341 | + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session | ||
| 342 | + // 创建session,内部配置的是stateful | ||
| 343 | + KieSession session = kieBase.newKieSession(); | ||
| 344 | + | ||
| 345 | + // 设置gloable对象,在drl中通过别名使用 | ||
| 346 | + session.setGlobal("validResult", result); | ||
| 347 | + session.setGlobal("log", logger); // 设置日志 | ||
| 348 | + | ||
| 349 | + // 载入数据 | ||
| 350 | + session.insert(validateParam); | ||
| 351 | + for (SchedulePlanInfo schedulePlanInfo: planResult.getSchedulePlanInfos()) { | ||
| 352 | + session.insert(schedulePlanInfo); | ||
| 353 | + } | ||
| 354 | + | ||
| 355 | + // 执行rule | ||
| 356 | + session.fireAllRules(); | ||
| 357 | + | ||
| 358 | + // 执行完毕销毁,有日志的也要关闭 | ||
| 359 | + session.dispose(); | ||
| 360 | + | ||
| 361 | +// for (ValidateResults_output.ValidInfo validInfo: result.getInfos()) { | ||
| 362 | +// logger.info(validInfo.getDesc()); | ||
| 363 | +// } | ||
| 364 | + | ||
| 365 | + // 取10条错误 | ||
| 366 | + int size = result.getInfos().size() > 10 ? 10: result.getInfos().size(); | ||
| 367 | + List<String> desclist = new ArrayList<>(); | ||
| 368 | + for (int i = 0; i < size; i++) { | ||
| 369 | + desclist.add(result.getInfos().get(i).getDesc()); | ||
| 370 | + } | ||
| 371 | + if (desclist.size() > 0) { | ||
| 372 | + schedulePlan.setPlanResult(StringUtils.join(desclist, "</br>")); | ||
| 373 | + } else { | ||
| 374 | + schedulePlan.setPlanResult("ok"); | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + // TODO:设定错误信息 | ||
| 378 | + } | ||
| 379 | + | ||
| 324 | @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) | 380 | @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) |
| 325 | public SchedulePlan save(SchedulePlan schedulePlan) { | 381 | public SchedulePlan save(SchedulePlan schedulePlan) { |
| 326 | // pre、如果排班的数据之前已经有了,删除之前的数据 | 382 | // pre、如果排班的数据之前已经有了,删除之前的数据 |
| @@ -341,6 +397,9 @@ public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> im | @@ -341,6 +397,9 @@ public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> im | ||
| 341 | // 3、确定套跑规则 | 397 | // 3、确定套跑规则 |
| 342 | rerunPlanResult(planResult, schedulePlan); | 398 | rerunPlanResult(planResult, schedulePlan); |
| 343 | 399 | ||
| 400 | + // TODO:3-1、验证排班结果 | ||
| 401 | + validPlanResult(planResult, schedulePlan); | ||
| 402 | + | ||
| 344 | // 4、保存数据(jdbcTemplate 批量插入) | 403 | // 4、保存数据(jdbcTemplate 批量插入) |
| 345 | Date start4 = new Date(); | 404 | Date start4 = new Date(); |
| 346 | scheduleRuleService.generateSchedulePlan(schedulePlan, planResult.getSchedulePlanInfos()); | 405 | scheduleRuleService.generateSchedulePlan(schedulePlan, planResult.getSchedulePlanInfos()); |
src/main/java/com/bsth/service/schedule/rules/MyDroolsConfiguration.java
| @@ -74,6 +74,9 @@ public class MyDroolsConfiguration { | @@ -74,6 +74,9 @@ public class MyDroolsConfiguration { | ||
| 74 | kfs.write("src/main/resources/rerun.drl", kieServices.getResources() | 74 | kfs.write("src/main/resources/rerun.drl", kieServices.getResources() |
| 75 | .newInputStreamResource(this.getClass().getResourceAsStream( | 75 | .newInputStreamResource(this.getClass().getResourceAsStream( |
| 76 | "/rules/rerun.drl"), "UTF-8")); | 76 | "/rules/rerun.drl"), "UTF-8")); |
| 77 | + kfs.write("src/main/resources/validplan.drl", kieServices.getResources() | ||
| 78 | + .newInputStreamResource(this.getClass().getResourceAsStream( | ||
| 79 | + "/rules/validplan.drl"), "UTF-8")); | ||
| 77 | // TODO:还有其他drl.... | 80 | // TODO:还有其他drl.... |
| 78 | 81 | ||
| 79 | // 4、创建KieBuilder,使用KieFileSystem构建 | 82 | // 4、创建KieBuilder,使用KieFileSystem构建 |
src/main/java/com/bsth/service/schedule/rules/validate/ValidRepeatBcFunction.java
0 → 100644
| 1 | +package com.bsth.service.schedule.rules.validate; | ||
| 2 | + | ||
| 3 | +import com.bsth.entity.schedule.SchedulePlanInfo; | ||
| 4 | +import org.kie.api.runtime.rule.AccumulateFunction; | ||
| 5 | + | ||
| 6 | +import java.io.*; | ||
| 7 | +import java.text.SimpleDateFormat; | ||
| 8 | +import java.util.ArrayList; | ||
| 9 | +import java.util.HashMap; | ||
| 10 | +import java.util.List; | ||
| 11 | +import java.util.Map; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 计算班次重复错误。 | ||
| 15 | + * 同一个路牌下,相同发车时间的班次数。 | ||
| 16 | + * 注意:使用这个函数时,要一天计算一次,多天计算无意义。 | ||
| 17 | + */ | ||
| 18 | +public class ValidRepeatBcFunction implements AccumulateFunction { | ||
| 19 | + @Override | ||
| 20 | + public void writeExternal(ObjectOutput out) throws IOException { | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { | ||
| 25 | + | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + protected static class RepeatBcInfo implements Externalizable { | ||
| 29 | + /** 错误描述 */ | ||
| 30 | + public List<ValidateResults_output.ValidInfo> validInfoList = new ArrayList<>(); | ||
| 31 | + /** 内部计数Map,key:{路牌Id}_{发车时间},value:个数 */ | ||
| 32 | + public Map<String, Integer> lpBcFcsjCount = new HashMap<>(); | ||
| 33 | + | ||
| 34 | + public RepeatBcInfo() { | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Override | ||
| 38 | + public void writeExternal(ObjectOutput out) throws IOException { | ||
| 39 | + out.writeObject(validInfoList); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { | ||
| 44 | + validInfoList = (List<ValidateResults_output.ValidInfo>) in.readObject(); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Override | ||
| 49 | + public Serializable createContext() { | ||
| 50 | + return new RepeatBcInfo(); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Override | ||
| 54 | + public void init(Serializable serializable) throws Exception { | ||
| 55 | + // TODO: | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Override | ||
| 59 | + public void accumulate(Serializable context, Object o) { | ||
| 60 | + RepeatBcInfo repeatBcInfo = (RepeatBcInfo) context; | ||
| 61 | + SchedulePlanInfo schedulePlanInfo = (SchedulePlanInfo) o; | ||
| 62 | + | ||
| 63 | + String key = schedulePlanInfo.getLp() + "_" + schedulePlanInfo.getFcsj(); | ||
| 64 | + SimpleDateFormat sf = new SimpleDateFormat("yyyy年MM月dd日"); | ||
| 65 | + String infoformat = "日期(%s),路牌(%s),班次(%s),重复(%d)次"; | ||
| 66 | + if (repeatBcInfo.lpBcFcsjCount.get(key) == null) { | ||
| 67 | + repeatBcInfo.lpBcFcsjCount.put(key, 1); | ||
| 68 | + } else { | ||
| 69 | + int count = repeatBcInfo.lpBcFcsjCount.get(key) + 1; | ||
| 70 | + ValidateResults_output.ValidInfo validInfo = new ValidateResults_output.ValidInfo(); | ||
| 71 | + validInfo.setSd(schedulePlanInfo.getScheduleDate()); | ||
| 72 | + validInfo.setDesc(String.format( | ||
| 73 | + infoformat, | ||
| 74 | + sf.format(schedulePlanInfo.getScheduleDate()), | ||
| 75 | + schedulePlanInfo.getLpName(), | ||
| 76 | + schedulePlanInfo.getFcsj(), | ||
| 77 | + count)); | ||
| 78 | + repeatBcInfo.validInfoList.add(validInfo); | ||
| 79 | + repeatBcInfo.lpBcFcsjCount.put(key, count); | ||
| 80 | + } | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + @Override | ||
| 84 | + public boolean supportsReverse() { | ||
| 85 | + return false; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + @Override | ||
| 89 | + public void reverse(Serializable serializable, Object o) throws Exception { | ||
| 90 | + | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + @Override | ||
| 94 | + public Class<?> getResultType() { | ||
| 95 | + return List.class; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + @Override | ||
| 99 | + public Object getResult(Serializable context) throws Exception { | ||
| 100 | + RepeatBcInfo repeatBcInfo = (RepeatBcInfo) context; | ||
| 101 | + return repeatBcInfo.validInfoList; | ||
| 102 | + } | ||
| 103 | +} |
src/main/java/com/bsth/service/schedule/rules/validate/ValidateParam.java
| @@ -16,7 +16,9 @@ public class ValidateParam { | @@ -16,7 +16,9 @@ public class ValidateParam { | ||
| 16 | /** 间隔天数 */ | 16 | /** 间隔天数 */ |
| 17 | private Integer days; | 17 | private Integer days; |
| 18 | 18 | ||
| 19 | - public ValidateParam() { | 19 | + public ValidateParam(DateTime f, DateTime t) { |
| 20 | + this.fromDate = f; | ||
| 21 | + this.toDate = t; | ||
| 20 | Period period = new Period(fromDate, toDate, PeriodType.days()); | 22 | Period period = new Period(fromDate, toDate, PeriodType.days()); |
| 21 | days = period.getDays() + 1; | 23 | days = period.getDays() + 1; |
| 22 | } | 24 | } |
src/main/java/com/bsth/service/schedule/rules/validate/ValidateResults_output.java
| @@ -10,7 +10,7 @@ import java.util.List; | @@ -10,7 +10,7 @@ import java.util.List; | ||
| 10 | public class ValidateResults_output { | 10 | public class ValidateResults_output { |
| 11 | private List<ValidInfo> infos = new ArrayList<>(); | 11 | private List<ValidInfo> infos = new ArrayList<>(); |
| 12 | 12 | ||
| 13 | - static class ValidInfo { | 13 | + public static class ValidInfo { |
| 14 | /** 日期 */ | 14 | /** 日期 */ |
| 15 | private Date sd; | 15 | private Date sd; |
| 16 | /** 描述 */ | 16 | /** 描述 */ |
src/main/resources/application-dev.properties
| @@ -10,7 +10,7 @@ spring.jpa.show-sql= true | @@ -10,7 +10,7 @@ spring.jpa.show-sql= true | ||
| 10 | spring.datasource.driver-class-name= com.mysql.jdbc.Driver | 10 | spring.datasource.driver-class-name= com.mysql.jdbc.Driver |
| 11 | spring.datasource.url= jdbc:mysql://127.0.0.1/control?useUnicode=true&characterEncoding=utf-8&useSSL=false | 11 | spring.datasource.url= jdbc:mysql://127.0.0.1/control?useUnicode=true&characterEncoding=utf-8&useSSL=false |
| 12 | spring.datasource.username= root | 12 | spring.datasource.username= root |
| 13 | -spring.datasource.password= root | 13 | +spring.datasource.password= |
| 14 | 14 | ||
| 15 | #DATASOURCE | 15 | #DATASOURCE |
| 16 | spring.datasource.max-active=100 | 16 | spring.datasource.max-active=100 |
src/main/resources/rules/functions.drl
| @@ -4,4 +4,5 @@ import accumulate com.bsth.service.schedule.rules.ttinfo2.ErrorBcCountFunction e | @@ -4,4 +4,5 @@ import accumulate com.bsth.service.schedule.rules.ttinfo2.ErrorBcCountFunction e | ||
| 4 | import accumulate com.bsth.service.schedule.rules.shiftloop.GidsCountFunction gidscount; | 4 | import accumulate com.bsth.service.schedule.rules.shiftloop.GidsCountFunction gidscount; |
| 5 | import accumulate com.bsth.service.schedule.rules.shiftloop.GidFbTimeFunction gidfbtime; | 5 | import accumulate com.bsth.service.schedule.rules.shiftloop.GidFbTimeFunction gidfbtime; |
| 6 | import accumulate com.bsth.service.schedule.rules.ttinfo.LpInfoResultsFunction lpinforesult; | 6 | import accumulate com.bsth.service.schedule.rules.ttinfo.LpInfoResultsFunction lpinforesult; |
| 7 | -import accumulate com.bsth.service.schedule.rules.ttinfo.MinRuleQyrqFunction minruleqyrq | ||
| 8 | \ No newline at end of file | 7 | \ No newline at end of file |
| 8 | +import accumulate com.bsth.service.schedule.rules.ttinfo.MinRuleQyrqFunction minruleqyrq; | ||
| 9 | +import accumulate com.bsth.service.schedule.rules.validate.ValidRepeatBcFunction vrb; | ||
| 9 | \ No newline at end of file | 10 | \ No newline at end of file |
src/main/resources/rules/validplan.drl
| 1 | -// TODO: | ||
| 2 | \ No newline at end of file | 1 | \ No newline at end of file |
| 2 | +package com.bsth.service.schedule.rules.validate; | ||
| 3 | + | ||
| 4 | +import com.bsth.entity.schedule.SchedulePlanInfo; | ||
| 5 | + | ||
| 6 | +import org.joda.time.*; | ||
| 7 | +import java.util.*; | ||
| 8 | + | ||
| 9 | +import org.slf4j.Logger; | ||
| 10 | + | ||
| 11 | +// 全局日志类(一般使用调用此规则的service类) | ||
| 12 | +global Logger log; | ||
| 13 | + | ||
| 14 | +// 输出 | ||
| 15 | +global ValidateResults_output validResult; | ||
| 16 | + | ||
| 17 | +//------------------------- 第一阶段、构造循环体 ----------------------------// | ||
| 18 | + | ||
| 19 | +declare Loop_param | ||
| 20 | + start_date: DateTime // 开始日期(这个要不停的更新迭代) | ||
| 21 | + end_date: DateTime // 结束日期 | ||
| 22 | + sdays: Integer // 总共循环的天数 | ||
| 23 | +end | ||
| 24 | + | ||
| 25 | +rule "Calcu_Loop_param" | ||
| 26 | + salience 1000 | ||
| 27 | + when | ||
| 28 | + ValidateParam( | ||
| 29 | + $fd: fromDate, | ||
| 30 | + $ed: toDate, | ||
| 31 | + $days: days | ||
| 32 | + ) | ||
| 33 | + then | ||
| 34 | + Loop_param p = new Loop_param(); | ||
| 35 | + p.setStart_date($fd); | ||
| 36 | + p.setEnd_date($ed); | ||
| 37 | + p.setSdays($days); | ||
| 38 | + | ||
| 39 | + insert(p); | ||
| 40 | +end | ||
| 41 | + | ||
| 42 | +//------------------------- 第二阶段、验证计算 ----------------------------// | ||
| 43 | + | ||
| 44 | + | ||
| 45 | +rule "Valid_repeat_bc" // 验证是否存在重复班次 | ||
| 46 | + salience 600 | ||
| 47 | + when | ||
| 48 | + $lp: Loop_param($sd: start_date, $ed: end_date) | ||
| 49 | + eval($sd.isBefore($ed) || $sd.isEqual($ed)) | ||
| 50 | + $spiList: ArrayList() from collect (SchedulePlanInfo(scheduleDate.getTime() == $sd.millis)) | ||
| 51 | + $infos: ArrayList() from accumulate ($spi: SchedulePlanInfo() from $spiList, vrb($spi)) | ||
| 52 | + then | ||
| 53 | + // TODO: | ||
| 54 | +// log.info("日期={},班次重复错误数={}", $sd, $infos.size()); | ||
| 55 | + | ||
| 56 | + validResult.getInfos().addAll($infos); | ||
| 57 | + | ||
| 58 | + // 迭代 | ||
| 59 | + $lp.setStart_date($sd.plusDays(1)); | ||
| 60 | + update($lp); | ||
| 61 | + | ||
| 62 | +end | ||
| 63 | + | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + | ||
| 69 | + | ||
| 70 | + |
src/main/resources/static/pages/scheduleApp/module/core/schedulePlanManage/list.html
| @@ -9,7 +9,8 @@ | @@ -9,7 +9,8 @@ | ||
| 9 | <th style="width: 100%;">关联时刻表</th> | 9 | <th style="width: 100%;">关联时刻表</th> |
| 10 | <th style="width: 150px;">排班开始日期</th> | 10 | <th style="width: 150px;">排班开始日期</th> |
| 11 | <th style="width: 150px;">排班结束日期</th> | 11 | <th style="width: 150px;">排班结束日期</th> |
| 12 | - <th style="width: 250px;">排班人/操作时间</th> | 12 | + <th style="width: 150px;">排班人/操作时间</th> |
| 13 | + <th style="width: 100px;">状态</th> | ||
| 13 | <th style="width: 180px;">操作</th> | 14 | <th style="width: 180px;">操作</th> |
| 14 | </tr> | 15 | </tr> |
| 15 | <tr role="row" class="filter"> | 16 | <tr role="row" class="filter"> |
| @@ -60,6 +61,7 @@ | @@ -60,6 +61,7 @@ | ||
| 60 | </div> | 61 | </div> |
| 61 | </td> | 62 | </td> |
| 62 | <td></td> | 63 | <td></td> |
| 64 | + <td></td> | ||
| 63 | <td> | 65 | <td> |
| 64 | <button class="btn btn-sm green btn-outline filter-submit margin-bottom" | 66 | <button class="btn btn-sm green btn-outline filter-submit margin-bottom" |
| 65 | ng-click="ctrl.doPage()"> | 67 | ng-click="ctrl.doPage()"> |
| @@ -94,9 +96,28 @@ | @@ -94,9 +96,28 @@ | ||
| 94 | <span ng-bind="info.scheduleToTime | date: 'yyyy-MM-dd '"></span> | 96 | <span ng-bind="info.scheduleToTime | date: 'yyyy-MM-dd '"></span> |
| 95 | </td> | 97 | </td> |
| 96 | <td> | 98 | <td> |
| 97 | - <span ng-bind="info.updateBy.userName"></span> | ||
| 98 | - / | ||
| 99 | - <span ng-bind="info.updateDate | date: 'yyyy-MM-dd HH:mm:ss'"></span> | 99 | + <div> |
| 100 | + <a href="#"> | ||
| 101 | + <i class="fa fa-user"></i> | ||
| 102 | + <span ng-bind="info.updateBy.userName"></span> | ||
| 103 | + </a> | ||
| 104 | + </div> | ||
| 105 | + <div> | ||
| 106 | + <a href="#"> | ||
| 107 | + <span ng-bind="info.updateDate | date: 'yyyy-MM-dd HH:mm:ss'"></span> | ||
| 108 | + </a> | ||
| 109 | + </div> | ||
| 110 | + | ||
| 111 | + </td> | ||
| 112 | + <td> | ||
| 113 | + <a href="#" class="btn btn-success btn-sm" ng-if="info.planResult == 'ok'"> | ||
| 114 | + <span>成功</span> | ||
| 115 | + </a> | ||
| 116 | + <a sweetalert | ||
| 117 | + sweet-options="{title: '排班错误信息',text: '线路:' + info.xl.name + '</br>开始时间:' + ctrl.toDateStr(info.scheduleFromTime) + '</br>结束时间:' + ctrl.toDateStr(info.scheduleToTime) + '</br>' + info.planResult, html: true,type: 'warning',showCancelButton: true,confirmButtonColor: '#DD6B55',confirmButtonText: '是',cancelButtonText: '取消'}" | ||
| 118 | + sweet-on-confirm="" | ||
| 119 | + class="btn btn-danger btn-sm" | ||
| 120 | + ng-if="info.planResult != 'ok'">点击查错</a> | ||
| 100 | </td> | 121 | </td> |
| 101 | <td> | 122 | <td> |
| 102 | <!--<a href="details.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm"> 详细 </a>--> | 123 | <!--<a href="details.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm"> 详细 </a>--> |
src/main/resources/static/pages/scheduleApp/module/core/scheduleRuleManage/list.html