Commit 46a5ecce by 王力

Merge branch 'dev_assign' into 'develop'

重命名

See merge request !179
2 parents a29bd11d 1d54846e
package com.dituhui.pea.order.common;
import com.dituhui.pea.dispatch.pojo.Location;
import com.dituhui.pea.order.dao.EngineerBusinessMPDao;
import com.dituhui.pea.order.dao.OrderAppointmentMPDao;
import com.dituhui.pea.order.dao.OrderRequestMPDao;
import com.dituhui.pea.order.dao.SkillInfoMPDao;
import com.dituhui.pea.order.entity.EngineerBusiness;
import com.dituhui.pea.order.entity.OrderAppointment;
import com.dituhui.pea.order.entity.OrderRequest;
import com.dituhui.pea.order.entity.SkillInfo;
import com.dituhui.pea.dispatch.common.GeoDistanceCalculator;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class OrderAssign {
private String orderId;
private String engineerCode;
@Autowired
OrderRequestMPDao orderRequestMPDao;
@Autowired
OrderAppointmentMPDao orderAppointmentMPDao;
@Autowired
SkillInfoMPDao skillInfoMPDao;
@Autowired
EngineerBusinessMPDao engineerBusinessMPDao;
public OrderAssign(String orderId, String engineerCode) {
this.orderId = orderId;
this.engineerCode = engineerCode;
}
@Data
public class Result {
private Boolean canAssign;
private String message;
private int minuteAddition;
private int distanceAddition;
private LocalDateTime start;
private LocalDateTime end;
public Result(boolean canAssign, String message, int minuteAddition, int distanceAddition, LocalDateTime start, LocalDateTime end){
this.canAssign = canAssign;
this.message = message;
this.minuteAddition = minuteAddition;
this.distanceAddition = distanceAddition;
this.start = start;
this.end = end;
}
}
public Result orderAssignCheck() {
OrderRequest order = orderRequestMPDao.getByOrderId(this.orderId);
double curX = Double.parseDouble(order.getX());
double curY = Double.parseDouble(order.getY());
// 获取技能需要的时长(分钟)
SkillInfo skillInfo = skillInfoMPDao.getByBrandAndTypeAndSkill(order.getBrand(), order.getType(), order.getSkill());
int takeTime = skillInfo.getTakeTime();
// 获取客户期望时间段
int start = this.timestamp2Point(order.getExpectTimeBegin());
int end = this.timestamp2Point(order.getExpectTimeEnd());
// 获取技术员的已分配订单的时间段, 根据时间段排序
List<OrderSegment> orderSegments = getEngineerOrderSegments(engineerCode, order.getDt());
// 转化为SegmentInsertion需要的时间段
List<SegmentInsertion.Segment> segments = this.orderSegment2Segment(orderSegments);
int index = SegmentInsertion.insertSegment(takeTime, start, end, segments);
if (index == -1) {
return new Result(false, "没有连续可插入空间(没计算时间)", 0, 0, null, null);
}
// 计算距离 & 时间
if(index == 0) {
// 第一订单为出发地
EngineerBusiness b = engineerBusinessMPDao.getByEngineerCode(engineerCode);
OrderSegment post = orderSegments.get(1);
OrderSegment pre = new OrderSegment(480, post.getStart(), Double.parseDouble(b.getX()), Double.parseDouble(b.getY()));
return this.getResult(curX, curY, pre, post, takeTime, order.getDt());
}
else if(index == orderSegments.size()) {
// 最后一个订单出发
OrderSegment pre = orderSegments.get(index);
// 为当前订单
OrderSegment post = new OrderSegment(start, end, Double.parseDouble(order.getX()), Double.parseDouble(order.getY()));
} else {
OrderSegment pre = orderSegments.get(index);
OrderSegment post = orderSegments.get(index+1);
return this.getResult(curX, curY, pre, post, takeTime, order.getDt());
}
return null;
}
private List<OrderSegment> getEngineerOrderSegments(String engineerCode, LocalDate dt) {
List<OrderSegment> orderSegments = new ArrayList<>();
List<OrderAppointment> appointments = orderAppointmentMPDao.selectByEngineerCodeAndDt(engineerCode, dt);
List<String> orderIds = new ArrayList<>();
for (OrderAppointment o: appointments) {
// 过滤掉已经取消的订单
if(o.getStatus().equals("NOT_ASSIGNED") || o.getStatus().equals("CANCELED")) {
continue;
}
orderIds.add(o.getOrderId());
}
Map<String, List<OrderAppointment>> m = appointments.stream().collect(Collectors.groupingBy(OrderAppointment::getOrderId));
List<OrderRequest> orderRequests = orderRequestMPDao.selectByOrderIds(orderIds);
for(OrderRequest o: orderRequests) {
List<OrderAppointment> tmp = m.getOrDefault(o.getOrderId(), new ArrayList<>());
if(tmp.isEmpty()) {
continue;
}
OrderAppointment oa = tmp.get(0);
OrderSegment seg = new OrderSegment();
seg.setOrderId(o.getOrderId());
seg.setX(Double.parseDouble(o.getX()));
seg.setY(Double.parseDouble(o.getY()));
seg.setStart(this.timestamp2Point(oa.getExpectStartTime()));
seg.setEnd(this.timestamp2Point(oa.getExpectEndTime()));
orderSegments.add(seg);
}
return orderSegments.stream().sorted(Comparator.comparing(OrderSegment::getStart)).collect(Collectors.toList());
}
private List<SegmentInsertion.Segment> orderSegment2Segment(List<OrderSegment> orderSegments) {
List<SegmentInsertion.Segment> segments = new ArrayList<>();
for (OrderSegment s: orderSegments) {
segments.add(new SegmentInsertion.Segment(s.getOrderId(), s.getStart(), s.getEnd()));
}
return segments;
}
private Result getResult(double curX, double curY, OrderSegment pre, OrderSegment post, int takeTime, LocalDate dt) {
Pair preCurPair = this.getDistanceAndDuration(pre.getX(), pre.getY(), curX, curY);
Pair postCurPair = this.getDistanceAndDuration(post.getX(), post.getY(), curX, curY);
Pair prePostPair = this.getDistanceAndDuration(post.getX(), post.getY(), pre.getX(), pre.getY());
// 判断增加时间+距离后,时间是否重叠了
int distance = post.getStart() - postCurPair.getDuration() - (pre.getEnd() + preCurPair.getDuration());
if(distance < takeTime) {
// 不支持插入
return new Result(false, "增加时间路程后,不支持插入", 0, 0, null, null);
}
// 插入点(时间点)
int startInsert = pre.getEnd() + preCurPair.getDuration();
int endInsert = startInsert + takeTime;
LocalDateTime startDateTime = this.point2LocalDateTime(startInsert, dt);
LocalDateTime endDateTime = this.point2LocalDateTime(endInsert, dt);
int minuteAddition = preCurPair.getDuration() + postCurPair.getDuration() - prePostPair.getDuration();
int distanceAddition = preCurPair.getDistance() + postCurPair.getDistance() - prePostPair.getDistance();
return new Result(true, "success", minuteAddition, distanceAddition, startDateTime, endDateTime);
}
private int timestamp2Point(Timestamp t) {
LocalDateTime dt = t.toLocalDateTime();
return dt.getHour() * 60 + dt.getMinute();
}
private LocalTime point2LocalTime(int point) {
int hour = point / 60;
int minute = point % 60;
return LocalTime.of(hour, minute, 0);
}
private LocalDateTime point2LocalDateTime(int point, LocalDate dt) {
return LocalDateTime.of(dt, this.point2LocalTime(point));
}
private Pair getDistanceAndDuration(double x1, double y1, double x2, double y2){
Location from = new Location(1, "1", "1", x1, y1);
Location to = new Location(2, "2", "2", x2, y2);
GeoDistanceCalculator cal= new GeoDistanceCalculator();
int distance = (int) cal.calculateDistance(from, to); // 单位为米
int duration = distance / (19 * 1000 / 60); // 时间为分钟,假设电动车速度为19km/h
return new Pair(distance, duration);
}
}
@Data
class OrderSegment{
private String orderId;
private int start;
private int end;
private double x;
private double y;
public OrderSegment(){
}
public OrderSegment(int start, int end, double x, double y){
this.start = start;
this.end = end;
this.x = x;
this.y = y;
}
}
@Data
class Pair{
private int distance;
private int duration;
public Pair(int distance, int duration){
this.distance = distance;
this.duration = duration;
}
}
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!