Commit 8312e0fa by Ren Ping

feat:移除不满足工程师时间窗强约束的订单

1 parent f83b0d31
...@@ -76,6 +76,9 @@ public class DispatchConstraintProvider implements ConstraintProvider { ...@@ -76,6 +76,9 @@ public class DispatchConstraintProvider implements ConstraintProvider {
if (!in) { if (!in) {
// 到达时间在日历窗口外,惩罚得分 // 到达时间在日历窗口外,惩罚得分
ret = true; ret = true;
customer.setInTechnicianTimeWindows(false);
} else {
customer.setInTechnicianTimeWindows(true);
} }
} }
} }
......
...@@ -50,6 +50,8 @@ public class Customer { ...@@ -50,6 +50,8 @@ public class Customer {
// 离开时间 // 离开时间
// private Integer departureTime; // private Integer departureTime;
private boolean isInTechnicianTimeWindows = true;
public Customer() { public Customer() {
} }
...@@ -135,9 +137,9 @@ public class Customer { ...@@ -135,9 +137,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet."); // throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
} }
if (previousCustomer == null) { if (previousCustomer == null) {
return technician.getDepot().getLocation().getDistanceTo(technician.getVehicleType(),location); return technician.getDepot().getLocation().getDistanceTo(technician.getVehicleType(), location);
} }
return previousCustomer.getLocation().getDistanceTo(technician.getVehicleType(),location); return previousCustomer.getLocation().getDistanceTo(technician.getVehicleType(), location);
} }
/** /**
...@@ -151,9 +153,9 @@ public class Customer { ...@@ -151,9 +153,9 @@ public class Customer {
// throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet."); // throw new IllegalStateException("This method must not be called when the shadow variables are not initialized yet.");
} }
if (previousCustomer == null) { if (previousCustomer == null) {
return technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),location); return technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(), location);
} }
return previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),location); return previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(), location);
} }
@Override @Override
......
package com.dituhui.pea.dispatch.quartz.dispatch; package com.dituhui.pea.dispatch.quartz.dispatch;
import com.dituhui.pea.dispatch.common.RedissonUtil;
import com.dituhui.pea.dispatch.service.SchedulerService; import com.dituhui.pea.dispatch.service.SchedulerService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution; import org.quartz.DisallowConcurrentExecution;
...@@ -23,7 +24,7 @@ import javax.annotation.Resource; ...@@ -23,7 +24,7 @@ import javax.annotation.Resource;
@DisallowConcurrentExecution @DisallowConcurrentExecution
public class AutoDispatchJob extends QuartzJobBean { public class AutoDispatchJob extends QuartzJobBean {
public static final String TEAM_JOB_PREFIX="BOXI_TEAM_"; public static final String TEAM_JOB_PREFIX = "BOXI_TEAM_";
@Resource @Resource
private SchedulerService schedulerService; private SchedulerService schedulerService;
...@@ -36,6 +37,9 @@ public class AutoDispatchJob extends QuartzJobBean { ...@@ -36,6 +37,9 @@ public class AutoDispatchJob extends QuartzJobBean {
String teamId = name.substring(TEAM_JOB_PREFIX.length()); String teamId = name.substring(TEAM_JOB_PREFIX.length());
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
log.info(">>> 自动派工(teamId:{}) 自动任务开始", teamId); log.info(">>> 自动派工(teamId:{}) 自动任务开始", teamId);
/*RedissonUtil.lockOperation(AutoDispatchJob.TEAM_JOB_PREFIX + teamId, 60, () -> {
schedulerService.dispatchRun2(teamId);
});*/
schedulerService.dispatchRun2(teamId); schedulerService.dispatchRun2(teamId);
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
log.info(">>> 自动派工(teamId:{}) 自动任务结束,耗时:{}", teamId, end - start); log.info(">>> 自动派工(teamId:{}) 自动任务结束,耗时:{}", teamId, end - start);
......
...@@ -113,14 +113,6 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -113,14 +113,6 @@ public class SchedulerServiceImpl implements SchedulerService {
for (int i = 1; i <= nextDaysLimit; i++) { for (int i = 1; i <= nextDaysLimit; i++) {
String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE); String currDay = LocalDate.now().plusDays(i).format(DateTimeFormatter.ISO_LOCAL_DATE);
boolean finalCutOff = cutOff;
RedissonUtil.lockOperation(AutoDispatchJob.TEAM_JOB_PREFIX + teamId, 60, () -> {
dispatchRun2OneDay(teamId, currDay, today, finalCutOff);
});
}
}
private void dispatchRun2OneDay(String teamId, String currDay, String today, boolean cutOff) {
Optional<DispatchBatch> optional = dispatchBatchRepository.findByTeamIdAndBatchDate(teamId, currDay); Optional<DispatchBatch> optional = dispatchBatchRepository.findByTeamIdAndBatchDate(teamId, currDay);
if (optional.isPresent() if (optional.isPresent()
&& Objects.nonNull(optional.get().getCutoffedTime()) && Objects.nonNull(optional.get().getCutoffedTime())
...@@ -161,4 +153,5 @@ public class SchedulerServiceImpl implements SchedulerService { ...@@ -161,4 +153,5 @@ public class SchedulerServiceImpl implements SchedulerService {
//throw e; //throw e;
} }
} }
}
} }
\ No newline at end of file
...@@ -553,7 +553,6 @@ public class SolveServiceImpl implements SolveService { ...@@ -553,7 +553,6 @@ public class SolveServiceImpl implements SolveService {
// Date end = Date.from(localEndTime.atZone(ZoneId.systemDefault()).toInstant()); // Date end = Date.from(localEndTime.atZone(ZoneId.systemDefault()).toInstant());
log.info("算法结果回写dispatch, step3-逐个客户处理, teamId:{}, batchNo:{}, employ: {}, customer:{}, service-duration:{} ", teamId, batchNo, technician.getCode(), customer.getCode(), customer.getServiceDuration()); log.info("算法结果回写dispatch, step3-逐个客户处理, teamId:{}, batchNo:{}, employ: {}, customer:{}, service-duration:{} ", teamId, batchNo, technician.getCode(), customer.getCode(), customer.getServiceDuration());
log.info(customer.toString());
LocalDateTime customDateTime = LocalDateTime.parse(customer.getDt() + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); LocalDateTime customDateTime = LocalDateTime.parse(customer.getDt() + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime arriveTime = customDateTime.plusMinutes(customer.getArrivalTime()); LocalDateTime arriveTime = customDateTime.plusMinutes(customer.getArrivalTime());
LocalDateTime leaveTime = customDateTime.plusMinutes(customer.getDepartureTime()); LocalDateTime leaveTime = customDateTime.plusMinutes(customer.getDepartureTime());
......
...@@ -5,13 +5,12 @@ import static java.util.Comparator.comparing; ...@@ -5,13 +5,12 @@ import static java.util.Comparator.comparing;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.util.Arrays; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.optaplanner.constraint.streams.drools.DroolsConstraintStreamScoreDirector; import org.optaplanner.constraint.streams.drools.DroolsConstraintStreamScoreDirector;
...@@ -72,12 +71,12 @@ public class DispatchSolutionUtils { ...@@ -72,12 +71,12 @@ public class DispatchSolutionUtils {
startPath = technician.getDepot().getStartTime(); startPath = technician.getDepot().getStartTime();
// endPath = startPath + // endPath = startPath +
// customer.getLocation().getPathTimeTo(technician.getDepot().getLocation()); // customer.getLocation().getPathTimeTo(technician.getDepot().getLocation());
endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation()); endPath = startPath + technician.getDepot().getLocation().getPathTimeTo(technician.getVehicleType(), customer.getLocation());
} else { } else {
startPath = previousCustomer.getDepartureTime(); startPath = previousCustomer.getDepartureTime();
// endPath = startPath + // endPath = startPath +
// customer.getLocation().getPathTimeTo(previousCustomer.getLocation()); // customer.getLocation().getPathTimeTo(previousCustomer.getLocation());
endPath = startPath + previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(),customer.getLocation()); endPath = startPath + previousCustomer.getLocation().getPathTimeTo(technician.getVehicleType(), customer.getLocation());
} }
if (customer.getArrivalTime() > customer.getEndTime()) { if (customer.getArrivalTime() > customer.getEndTime()) {
...@@ -172,7 +171,7 @@ public class DispatchSolutionUtils { ...@@ -172,7 +171,7 @@ public class DispatchSolutionUtils {
return " var lines = " + lines; return " var lines = " + lines;
} else if (StringUtils.startsWith(line, " var names = ")) { } else if (StringUtils.startsWith(line, " var names = ")) {
return " var names = " + names; return " var names = " + names;
} else{ } else {
return line; return line;
} }
}).collect(Collectors.toList()); }).collect(Collectors.toList());
...@@ -366,6 +365,9 @@ public class DispatchSolutionUtils { ...@@ -366,6 +365,9 @@ public class DispatchSolutionUtils {
*/ */
public static void removeHardConstraintCustomer(DispatchSolution solution, public static void removeHardConstraintCustomer(DispatchSolution solution,
SolverFactory<DispatchSolution> solverFactory) { SolverFactory<DispatchSolution> solverFactory) {
if ("1719308075152764928".equals(solution.getTeamId())) {
System.out.println(solution.getTeamId());
}
SolutionManager<DispatchSolution, HardSoftLongScore> scoreManager = SolutionManager.create(solverFactory); SolutionManager<DispatchSolution, HardSoftLongScore> scoreManager = SolutionManager.create(solverFactory);
ScoreExplanation<DispatchSolution, HardSoftLongScore> scoreExplanation = scoreManager.explain(solution); ScoreExplanation<DispatchSolution, HardSoftLongScore> scoreExplanation = scoreManager.explain(solution);
Map<String, ConstraintMatchTotal<HardSoftLongScore>> constraintMatchTotalMap = scoreExplanation Map<String, ConstraintMatchTotal<HardSoftLongScore>> constraintMatchTotalMap = scoreExplanation
...@@ -382,17 +384,33 @@ public class DispatchSolutionUtils { ...@@ -382,17 +384,33 @@ public class DispatchSolutionUtils {
// 违反硬约束对象,根据具体约束返回不同类型对象 // 违反硬约束对象,根据具体约束返回不同类型对象
if (indictedObject instanceof Customer) { if (indictedObject instanceof Customer) {
Customer customer = (Customer) indictedObject; Customer customer = (Customer) indictedObject;
// 更新shadow变量 // 更新shadow变量
updateShadowVariable(customer); updateShadowVariable(customer);
// 移除技术员 // 移除技术员
customer.getTechnician().getCustomerList().remove(customer); customer.getTechnician().getCustomerList().remove(customer);
solution.getUnDispatchedCustomers().add(customer); solution.getUnDispatchedCustomers().add(customer);
} }
} }
break; break;
case technicianTimeWindowsMatch:
for (Object indictedObject : constraintMatch.getIndictedObjectList()) {
// 违反硬约束对象,根据具体约束返回不同类型对象
if (indictedObject instanceof Technician
&& ObjectUtil.isNotEmpty(((Technician) indictedObject).getCustomerList())) {
List<Customer> customerList = new ArrayList<>();
customerList.addAll(((Technician) indictedObject).getCustomerList());
for (Customer customer : customerList) {
if (!customer.isInTechnicianTimeWindows()) {
// 更新shadow变量
updateShadowVariable(customer);
// 移除技术员
customer.getTechnician().getCustomerList().remove(customer);
solution.getUnDispatchedCustomers().add(customer);
}
}
}
}
break;
default: default:
break; break;
} }
...@@ -415,13 +433,13 @@ public class DispatchSolutionUtils { ...@@ -415,13 +433,13 @@ public class DispatchSolutionUtils {
Customer nextCustomer = sourceCustomer.getNextCustomer(); Customer nextCustomer = sourceCustomer.getNextCustomer();
if (previousCustomer == null) { if (previousCustomer == null) {
// 当前订单是第一个订单 // 当前订单是第一个订单
if(null != nextCustomer) { if (null != nextCustomer) {
nextCustomer.setPreviousCustomer(null); nextCustomer.setPreviousCustomer(null);
} }
} }
if (nextCustomer == null) { if (nextCustomer == null) {
// 当前订单是最后一个订单 // 当前订单是最后一个订单
if(null != previousCustomer) { if (null != previousCustomer) {
previousCustomer.setNextCustomer(null); previousCustomer.setNextCustomer(null);
} }
} }
......
...@@ -3,8 +3,8 @@ server: ...@@ -3,8 +3,8 @@ server:
dispatch: dispatch:
cron: cron:
expr: 0 */3 8-23 * * ? expr: 0 10 8-23 * * ?
next-day-limit: 20 next-day-limit: 2
scheduler: scheduler:
init-engineer-capacity: init-engineer-capacity:
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!