Commit 7f799a68a88e95206eeded82336b1be0ebbacef1

Authored by 徐烜
1 parent a2d14a12

Update

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&lt;SchedulePlan, Long&gt; im @@ -341,6 +397,9 @@ public class SchedulePlanServiceImpl extends BServiceImpl&lt;SchedulePlan, Long&gt; 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
@@ -66,6 +66,7 @@ @@ -66,6 +66,7 @@
66 <td> 66 <td>
67 <div> 67 <div>
68 <a href="#"> 68 <a href="#">
  69 + <i class="fa fa-user"></i>
69 <span ng-bind="info.updateBy.userName"></span> 70 <span ng-bind="info.updateBy.userName"></span>
70 </a> 71 </a>
71 </div> 72 </div>