package com.xiaopeng.operation.utils; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.map.RouteAndFareDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.operation.VehiclePositionByVinDto; import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.operation.XpTradingStrategyClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpTradingStrategy; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpOrderReassign; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.OrderType; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.automaticPilot.protobuf.TaskActionType; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.operation.VehiclePositionVo; import com.xiaopeng.api.vo.operation.XpTargetedServiceVehicleVo; import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.Constants; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.operation.config.UidVinBindingConfig; import com.xiaopeng.operation.dto.PriorityMatchResult; import com.xiaopeng.operation.mapper.XpElectronicFenceMapper; import com.xiaopeng.operation.service.*; import com.xiaopeng.operation.utils.mango.VehiclePositionService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Slf4j @Component public class TaskOrderUtil { @Resource XpTargetedServiceService xpTargetedServiceService; @Resource private RedisService redisService; @Resource private XpPointService xpPointService; @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; @Resource private XpOrderClient xpOrderClient; @Resource private VehiclePositionService vehiclePositionService; @Resource private IXpTradingStrategyService xpTradingStrategyService; @Resource private XpCruiseOrderClient xpCruiseOrderClient; @Resource private XpTradingStrategyClient tradingStrategyClient; @Resource private XpVehicleClient xpVehicleClient; @Resource private RedissonClient redissonClient; @Resource private XpMapClient xpMapClient; // @Resource private OrderMissionClient orderMissionClient; @Resource private XpPushMessageClient xpPushMessageClient; @Resource private XpElectronicFenceMapper xpElectronicFenceMapper; @Resource private UidVinBindingConfig uidVinBindingConfig; @Resource private UidVinPriorityMatcher uidVinPriorityMatcher; @Resource private XpAppUserCouponClient xpAppUserCouponClient; // 自定义线程池 private static final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); // ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20); static { threadPoolTaskExecutor.setCorePoolSize(20); threadPoolTaskExecutor.setMaxPoolSize(100); threadPoolTaskExecutor.setQueueCapacity(20); threadPoolTaskExecutor.setKeepAliveSeconds(60); threadPoolTaskExecutor.setThreadNamePrefix("taskOrder-"); threadPoolTaskExecutor.initialize(); } /** * 5秒执行一次 * 播单 在下单的时候会存一个 redis 队列 */ @Scheduled(cron = "0/5 * * * * ?") public void taskOrder() { System.out.println("5秒执行一次"); Set quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); for (String name : quoteMatchName) { String firstElement = redisService.getFirstElement(name); if (firstElement != null) { String[] split = firstElement.split("_"); if(split.length>8){ String targetedVal = split[8]; if (!"0".equals(targetedVal)) { continue; } } // 如果未处理 创建新任务 if ("0".equals(split[2])) { String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { orderProcess(name, firstElement); }); } } } } /** * 定向订单 */ @Scheduled(cron = "0/5 * * * * ?") public void taskOrder_targeted() { System.out.println("5秒执行一次"); Set quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); for (String name : quoteMatchName) { String firstElement = redisService.getFirstElement(name); if (firstElement != null) { String[] split = firstElement.split("_"); if(split.length>8){ String targetedVal = split[8]; if (!"0".equals(targetedVal)) { // 如果未处理 创建新任务 if ("0".equals(split[2])) { String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { orderProcess(name, firstElement); }); } } } } } } /** * 订单处理 * @param quoteName 队列名称 * @param firstElement 队列第一个元素 */ private void orderProcess(String quoteName, String firstElement) { XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); String orderId = firstElement.split("_")[0]; String lonLat = firstElement.split("_")[1]; String uid = firstElement.split("_")[3]; String orderNo = firstElement.split("_")[4]; // 距离 String distance = firstElement.split("_")[5]; // 时间 String duration = firstElement.split("_")[6]; // 后台配置的规则 String planRule = firstElement.split("_")[7]; // 经纬度 String[] split = lonLat.split(","); // 5轮找车辆 //每次查找车辆推单后的等待秒数 int sleepTime = 3; Integer onePushTime = xpTradingStrategy.getOnePushTime(); Double onePushDistance = xpTradingStrategy.getOnePushDistance(); int count = onePushTime / sleepTime; // 第一轮推单 log.info("开始第一轮推单 {}", orderNo); Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第二轮推单 Integer twoPushTime = xpTradingStrategy.getTwoPushTime(); Double twoPushDistance = xpTradingStrategy.getTwoPushDistance(); count = twoPushTime / sleepTime; log.info("开始第二轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第三轮推单 Integer threePushTime = xpTradingStrategy.getThreePushTime(); Double threePushDistance = xpTradingStrategy.getThreePushDistance(); count = threePushTime / sleepTime; log.info("开始第三轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第四轮推单 Integer fourPushTime = xpTradingStrategy.getFourPushTime(); Double fourPushDistance = xpTradingStrategy.getFourPushDistance(); count = fourPushTime / sleepTime; log.info("开始第四轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第五轮推单 Integer fivePushTime = xpTradingStrategy.getFivePushTime(); Double fivePushDistance = xpTradingStrategy.getFivePushDistance(); count = fivePushTime / sleepTime; log.info("开始第五轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 取消订单 R xpOrderR = xpOrderClient.queryOrderById(Long.valueOf(orderId)); if (xpOrderR.getCode() == 200) { XpOrder xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() == 1) { log.info("五轮推单结束,无车辆接单,执行取消订单 {}", orderNo); xpOrderClient.cancelOrder(orderId); //推送订单状态给乘客 SendMessageDTO dto = new SendMessageDTO(); dto.setAppUserId(xpOrder.getAppUserId().toString()); dto.setMessage("{\"type\":\"ORDER_STATUS\",\"content\":\"{\\\"orderId\\\":\\\"" + orderId + "\\\",\\\"status\\\":0}\",\"timestamp\":\"" + System.currentTimeMillis() + "\"}"); R stringR = xpPushMessageClient.sendStatus(dto); //推送失败,重试3次 if(stringR.getCode() != Constants.SUCCESS){ ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); executor.execute(() -> { for (int i = 0; i < 3; i++) { R stringR1 = xpPushMessageClient.sendStatus(dto); if(stringR1.getCode() == Constants.SUCCESS){ break; } try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } log.info("五轮推单结束后,无车辆接单,推送取消消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(dto), xpOrder.getOrderNumber()); } }); } //将订单从队列中移除 log.info("五轮推单结束,无车辆接单,执行队列移除订单 {}", orderNo); redisService.popFirstElement(quoteName); } } } /** * 订单处理 * @param quoteName 队列名称 * @param count 轮数 * @param uid * @param split 经纬度 * @param orderNo 订单号 * @param xpTradingStrategy 规则 */ @SneakyThrows private Boolean processPushOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule) { log.info("进入推单环节 单号 {}", orderNo); if (count == 0) { count = 1; } // 订单状态 R xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { return false; } if (xpOrderR.getData().getStatus() != 1) { return true; } XpOrder xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() == 0) { redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); } // 找出围栏id Long xpElectronicFenceAreaId = xpOrder.getXpElectronicFenceAreaId(); Long electronicId = xpElectronicFenceAreaService.getById(xpElectronicFenceAreaId).getElectronicId(); XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(electronicId); // ===== 新增:UID-VIN 优先匹配(仅 enabled=true 时生效)===== log.info("[人车订单绑定测试] >>>>>> 进入优先匹配判断, uid={}, orderNo={}, 围栏区域ID={}", uid, orderNo, xpElectronicFenceAreaId); if (uidVinBindingConfig.isEnabled()) { log.info("[人车订单绑定测试] 总开关已开启, 开始执行优先匹配逻辑, uid={}, orderNo={}", uid, orderNo); try { PriorityMatchResult priorityResult = uidVinPriorityMatcher.tryPriorityMatch(uid, orderNo, String.valueOf(xpElectronicFenceAreaId)); log.info("[人车订单绑定测试] 优先匹配结果: matched={}, vin={}, failReason={}, uid={}, orderNo={}", priorityResult != null ? priorityResult.isMatched() : "null", priorityResult != null ? priorityResult.getVin() : "null", priorityResult != null ? priorityResult.getFailReason() : "null", uid, orderNo); if (priorityResult != null && priorityResult.isMatched()) { String priorityVin = priorityResult.getVin(); log.info("[人车订单绑定测试] 匹配成功, 准备获取分布式锁, lockKey=FIND_CAR_{}, orderNo={}", priorityVin, orderNo); RLock priorityLock = redissonClient.getLock("FIND_CAR_" + priorityVin); priorityLock.lock(10, TimeUnit.SECONDS); log.info("[人车订单绑定测试] 分布式锁获取成功, vin={}, orderNo={}", priorityVin, orderNo); try { // 二次校验车辆状态 log.info("[人车订单绑定测试] 开始二次校验车辆状态, vin={}, orderNo={}", priorityVin, orderNo); R vehicleR = xpVehicleClient.findByVehicleVin(priorityVin); log.info("[人车订单绑定测试] 二次校验-车辆查询结果: code={}, hasData={}, vin={}", vehicleR.getCode(), vehicleR.getData() != null, priorityVin); if (vehicleR.getCode() == 200 && vehicleR.getData() != null) { XpVehicle vehicle = vehicleR.getData(); log.info("[人车订单绑定测试] 二次校验-车辆状态: operatingStatus={}, state={}, vehicleType={}, vin={}", vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType(), priorityVin); if (vehicle.getOperatingStatus() == 1 && vehicle.getState() == 0 && vehicle.getVehicleType() != 1) { log.info("[人车订单绑定测试] 二次校验-车辆状态通过(空闲), 开始校验订单状态, orderNo={}", orderNo); // 二次校验订单状态 R orderCheck = xpOrderClient.queryOrderByOrderNo(orderNo); log.info("[人车订单绑定测试] 二次校验-订单查询结果: code={}, status={}, orderNo={}", orderCheck.getCode(), orderCheck.getData() != null ? orderCheck.getData().getStatus() : "null", orderNo); if (orderCheck.getCode() == 200 && orderCheck.getData() != null && orderCheck.getData().getStatus() == 1) { log.info("[人车订单绑定测试] 二次校验全部通过, 开始关闭巡游单, vin={}, orderNo={}", priorityVin, orderNo); // 关闭巡游单 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(priorityVin); log.info("[人车订单绑定测试] 关闭巡游单结果: code={}, vin={}, orderNo={}", stringR != null ? stringR.getCode() : "null", priorityVin, orderNo); if (stringR != null && stringR.getCode() == 200) { log.info("[人车订单绑定测试] 关闭巡游单成功, 开始下发XPU命令, vin={}, orderNo={}", priorityVin, orderNo); XpCruiseOrder cruiseOrder = stringR.getData(); // 下发XPU命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(priorityVin); pushOrderDto.setStartTaskId(orderCheck.getData().getXpuStartTaskId()); pushOrderDto.setEndTaskId(orderCheck.getData().getXpuEndTaskId()); pushOrderDto.setOrderId(orderCheck.getData().getId().toString()); pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat()); pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon()); pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat()); pushOrderDto.setEndLongitude(orderCheck.getData().getEndLon()); pushOrderDto.setEndPoiName(orderCheck.getData().getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); log.info("[人车订单绑定测试] XPU推单参数: vin={}, orderId={}, startLat={}, startLon={}, endLat={}, endLon={}, orderNo={}", priorityVin, orderCheck.getData().getId(), orderCheck.getData().getStartLat(), orderCheck.getData().getStartLon(), orderCheck.getData().getEndLat(), orderCheck.getData().getEndLon(), orderNo); orderMissionClient.pushOrder(pushOrderDto); log.info("[人车订单绑定测试] ====== 派单成功! uid={}, vin={}, orderNo={}, 从队列移除订单 ======", uid, priorityVin, orderNo); redisService.removeByPattern(quoteName, orderNo); return true; } else { log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo); } } else { log.info("[人车订单绑定测试] 二次校验-订单状态不满足(非待派单), 回退常规流程, orderNo={}", orderNo); } } else { if (vehicle.getState() != 0) { log.info("[人车订单绑定测试] 二次校验-车辆已接单(state={}), 当前有未完成订单, 无法指派, vin={}, plateNumber={}, orderNo={}", vehicle.getState(), priorityVin, vehicle.getPlateNumber(), orderNo); } else { log.info("[人车订单绑定测试] 二次校验-车辆状态不满足, 回退常规流程, vin={}, operatingStatus={}, state={}, vehicleType={}", priorityVin, vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType()); } } } else { log.info("[人车订单绑定测试] 二次校验-车辆查询失败, 回退常规流程, vin={}, code={}", priorityVin, vehicleR.getCode()); } } catch (Exception e) { log.error("[人车订单绑定测试] 锁内执行异常,回退常规流程, uid={}, vin={}, orderNo={}", uid, priorityVin, orderNo, e); } finally { priorityLock.unlock(); log.info("[人车订单绑定测试] 分布式锁已释放, vin={}, orderNo={}", priorityVin, orderNo); } } else { log.info("[人车订单绑定测试] 优先匹配未命中, 进入常规流程, uid={}, orderNo={}", uid, orderNo); } } catch (Exception e) { log.error("[人车订单绑定测试] 优先匹配过程异常,回退常规流程, uid={}, orderNo={}", uid, orderNo, e); } } else { log.info("[人车订单绑定测试] 总开关未开启(enabled=false), 跳过优先匹配, uid={}, orderNo={}", uid, orderNo); } // ===== 新增结束 ===== //根据 用户id 和 城市编码 查询 定向服务的 车辆信息 List targetedServiceVehicleVinList = xpTargetedServiceService.findSetVehicleVinByUserIdAndCityCode(xpOrder.getAppUserId(), xpOrder.getCityCode()); for (int i = 0; i < count; i++) { //等到sleepTime秒钟 Thread.sleep(sleepTime * 1000); // 根据距离找车 // 车多则根据配置找具体车数量 根据距离最近 // 更改 暂不限制数量 List positionList = vehiclePositionService.findAvailableVehiclesNearby(Double.parseDouble(split[0]), Double.parseDouble(split[1]), pushDistance, xpTradingStrategy.getSimultaneouslyOrderCount()); log.info("根据距离找车 {} 距离 {}KM 经度 {} 维度 {} 查找结果 {} 单号 {}", orderNo, pushDistance, split[0], split[1], positionList, orderNo); // 获取车辆的区域信息 if (positionList.isEmpty()) { continue; } Set vinList = positionList.stream().map(VehiclePosition::getVin).collect(Collectors.toSet()); // 获取车辆的信息 筛选出可用车辆 R> vehiclePositionVos = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount())); log.info("筛选可用车辆结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); if (vehiclePositionVos.getCode() != 200) { continue; } List data = vehiclePositionVos.getData(); //指定区域的车 // 计算交集:指定区域的车辆 与 定向服务车辆列表的交集 if (targetedServiceVehicleVinList != null && !targetedServiceVehicleVinList.isEmpty() && data != null) { Collection newVehicleVinList = CollUtil.intersection(data,targetedServiceVehicleVinList); if(CollUtil.isNotEmpty(newVehicleVinList)){ data = (List) newVehicleVinList; } } List availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class); // 找出符合条件的 List finalData = data; availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> finalData.contains(e.getVin())).collect(Collectors.toList()); // List availableVehiclesNearby =vehiclePositionVos.getData(); if (!availableVehiclesNearby.isEmpty()) { if (availableVehiclesNearby.size() > 1) { log.info("附近有 {} 辆车,进入权重判断流程 单号 {}", availableVehiclesNearby.size(), orderNo); // 走权重 // 订单价值 Integer tendencyOrderValue = xpTradingStrategy.getTendencyOrderValue(); // 距离价值 Integer tendencyDistance = xpTradingStrategy.getTendencyDistance(); // 时间价值 Integer tendencyTime = xpTradingStrategy.getTendencyTime(); try { // 电量价值 Integer tendencyElectricity = xpTradingStrategy.getTendencyElectricity(); // 找出最大的值是那个 Integer max = Math.max(tendencyOrderValue, Math.max(tendencyDistance, Math.max(tendencyTime, tendencyElectricity))); if (max.equals(tendencyOrderValue)) { // 订单价值 // 时间差权重 Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference(); // 距离差权重 Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference(); // 距离权重 Integer weightDistance = xpTradingStrategy.getWeightDistance(); // 时间权重 Integer weightTime = xpTradingStrategy.getWeightTime(); // 电量权重 Integer weightElectricity = xpTradingStrategy.getWeightElectricity(); // 找出最大的值是那个 Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity)))); // 时间差 if (max1.equals(weightTimeDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration(); vehiclePosition.setTimeDifference(durationDifference); } } } // 距离差 if (max1.equals(weightDistanceDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance(); vehiclePosition.setDistanceDifference(distanceDifference); } } } if (max1.equals(weightDistance)) { log.info("车子距离~~"); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo); vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); double score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistance(score); score--; } } if (max1.equals(weightTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setSecond(score); score--; } } if (max1.equals(weightElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size = tendencyElectricity; // 做比对的分数 int temp = availableVehiclesNearby.get(0).getCurrentElectricity(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size); if (temp != vehiclePosition.getCurrentElectricity()) { size--; } } } // 算出总分 再来排序计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue()); } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList()); int size = tendencyOrderValue; // 做比对的分数 double temp = availableVehiclesNearby.get(0).getOrderValueTotal(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size); if (temp != vehiclePosition.getOrderValueTotal()) { size--; } } } // 距离分数 if (max.equals(tendencyDistance)) { log.info("车子距离~~"); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo); vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } // availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); // int size = tendencyDistance; // // 做比对的分数 // double temp = availableVehiclesNearby.get(0).getDistance(); // for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { // vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size); // if (temp != vehiclePosition.getDistance()) { // size--; // } // } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistanceScore(score); score--; } } // 时间分数 if (max.equals(tendencyTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setTimeScore(score); score--; } // availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); // int size = tendencyTime; // // 做比对的分数 // double temp = availableVehiclesNearby.get(0).getSecond(); // for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { // vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size); // if (temp != vehiclePosition.getSecond()) { // size--; // } // } } // 电量分数 if (max.equals(tendencyElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size = tendencyElectricity; // 做比对的分数 int temp = availableVehiclesNearby.get(0).getCurrentElectricity(); int maxTemp = 0; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size); if (temp != vehiclePosition.getCurrentElectricity()) { size--; } else { maxTemp++; } } if (maxTemp > 1) { // 证明有最高相同电量的 找下一个 // 找出最第二大的值是那个 // 将四个值放入列表 List values = Arrays.asList(tendencyOrderValue, tendencyDistance, tendencyTime); // 降序排序 values.sort(Collections.reverseOrder()); // 获取第二大值 Integer secondMax = values.get(1); // 判断第二大的是哪个 if (Objects.equals(secondMax, tendencyDistance)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); int size1 = tendencyDistance; // 做比对的分数 double temp1 = availableVehiclesNearby.get(0).getDistance(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size1); if (temp1 != vehiclePosition.getDistance()) { size1--; } } } if (Objects.equals(secondMax, tendencyTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int size1 = tendencyTime; // 做比对的分数 double temp1 = availableVehiclesNearby.get(0).getSecond(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size1); if (temp1 != vehiclePosition.getSecond()) { size1--; } } } // 订单价值 if (Objects.equals(secondMax, tendencyOrderValue)) { // 订单价值 // 时间差权重 Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference(); // 距离差权重 Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference(); // 距离权重 Integer weightDistance = xpTradingStrategy.getWeightDistance(); // 时间权重 Integer weightTime = xpTradingStrategy.getWeightTime(); // 电量权重 Integer weightElectricity = xpTradingStrategy.getWeightElectricity(); // 找出最大的值是那个 Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity)))); // 时间差 if (max1.equals(weightTimeDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration(); vehiclePosition.setTimeDifference(durationDifference); } } } if (max1.equals(weightDistanceDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance(); vehiclePosition.setDistanceDifference(distanceDifference); } } } if (max1.equals(weightDistance)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } } if (max1.equals(weightTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } } if (max1.equals(weightElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size1 = tendencyElectricity; // 做比对的分数 int temp1 = availableVehiclesNearby.get(0).getCurrentElectricity(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size1); if (temp1 != vehiclePosition.getCurrentElectricity()) { size1--; } } } } // 算出总分 再来排序计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue()); } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList()); int size2 = tendencyOrderValue; // 做比对的分数 double temp2 = availableVehiclesNearby.get(0).getOrderValueTotal(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size2); if (temp2 != vehiclePosition.getOrderValueTotal()) { size2--; } } } } } catch (Exception e) { log.error("异常", e); } // 判断总分来计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getValueScore()); } VehiclePositionVo vehiclePositionVo = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getTotal).reversed()).collect(Collectors.toList()).get(0); // // VehiclePositionVo vehiclePositionVo1 = vehiclePositionVo; RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin()); lock.lock(10, TimeUnit.SECONDS); log.info("队列 {} 车辆 {} 单号 {}", quoteName, vehiclePositionVo.getVin(), orderNo); try { // VehiclePosition vehiclePosition = vehiclePositionService.findByVehicleId(vehiclePositionVo.getVehicle_id()); R vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin()); if (vehiclePositionR.getCode() != 200) { continue; } XpVehicle vehiclePosition = vehiclePositionR.getData(); log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo); log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getStatus(), orderNo); if (vehiclePosition.getOperatingStatus() != 1 || vehiclePosition.getState() != 0 || vehiclePosition.getVehicleType() == 1) { continue; } // 再次查询一下订单 看是否取消 xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { continue; } xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() != 1) { continue; } // 关闭巡游单子 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin()); if (stringR == null || stringR.getCode() != 200) { log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber()); continue; } log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo); XpCruiseOrder cruiseOrder = stringR.getData(); // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId()); pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); pushOrderDto.setVin(vehiclePosition.getVehicleVin()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setStartLatitude(xpOrder.getStartLat()); pushOrderDto.setStartLongitude(xpOrder.getStartLon()); pushOrderDto.setEndLatitude(xpOrder.getEndLat()); pushOrderDto.setEndLongitude(xpOrder.getEndLon()); pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo); redisService.removeByPattern(quoteName,xpOrder.getOrderNumber()); log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); return true; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } else { // 直接派单 定义一个锁来锁定车辆 VehiclePositionVo vehiclePosition = availableVehiclesNearby.get(0); String vehicleVin = vehiclePosition.getVin(); RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePosition.getVin()); lock.lock(10, TimeUnit.SECONDS); try { // 查询车辆状态 R vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if (vehicleR.getCode() != 200) { continue; } XpVehicle vehicleId1 = vehicleR.getData(); log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo); log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo); if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) { continue; } // 再次查询一下订单 看是否取消 xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { continue; } xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() != 1) { continue; } // 关闭巡游单子 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin()); if (stringR == null || stringR.getCode() != 200) { log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber()); continue; } log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo); XpCruiseOrder cruiseOrder = stringR.getData(); // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId()); pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); pushOrderDto.setVin(vehiclePosition.getVin()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setStartLatitude(xpOrder.getStartLat()); pushOrderDto.setStartLongitude(xpOrder.getStartLon()); pushOrderDto.setEndLatitude(xpOrder.getEndLat()); pushOrderDto.setEndLongitude(xpOrder.getEndLon()); pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber()); redisService.popFirstElement(quoteName); log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); return true; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } log.info("没有找到空闲车辆 {},尝试连环派单给即将服务结束的车辆", orderNo); // 查询状态为1的车辆vin R> servingVehicles = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount(),1)); if (servingVehicles.getCode() != 200) { continue; } LonLatDto userPostion = new LonLatDto(Double.parseDouble(split[0]), Double.parseDouble(split[1])); XpTradingStrategyDetailVO strategyDetailVO = tradingStrategyClient.queryById().getData(); Integer distanceRegardAsEnding = strategyDetailVO.getDistanceRegardAsEnding(); Integer timeRegardAsEnding = strategyDetailVO.getTimeRegardAsEnding(); Integer backupPower = strategyDetailVO.getBackupPower(); Integer destToPassenger = strategyDetailVO.getDestToPassenger(); Integer endingTimeToUseTime = strategyDetailVO.getEndingTimeToUseTime(); LocalDateTime rideTime = xpOrder.getRideTime(); LocalDateTime now = LocalDateTime.now(); Optional luckyOrderOpt = servingVehicles.getData().stream() //获取位置 .map(vin -> mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class)) .map(VehiclePosition::getOrderId) .map(xpOrderClient::queryOrderById) .filter(R::isSuccess) .map(R::getData) .filter(o -> { XpVehicle xpVehicle = xpVehicleClient.queryById(o.getVehicleId()).getData(); Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(o.getAppUserId().toString())); RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class); if (routeRemain.getDuration() / 60 > timeRegardAsEnding) { return false; } if (routeRemain.getDistance() > distanceRegardAsEnding) { return false; } if (routeRemain.getDuration() / 60 > timeRegardAsEnding) { return false; } RouteAndFareDto next = new RouteAndFareDto(); next.setOrigin(new LonLatDto(o.getStartLon(),o.getStartLat())); next.setDestination(new LonLatDto(o.getEndLon(),o.getEndLat())); RouteVo route = xpMapClient.getDistanceAndDuration(next).getData(); if (route.getDistance() > backupPower + xpVehicle.getMileageRange()) return false; return routeRemain.getDistance() < destToPassenger || now.plusSeconds(routeRemain.getDuration()) .plusMinutes(endingTimeToUseTime) .isBefore(rideTime); }) .findAny(); if (luckyOrderOpt.isPresent()) { XpOrder luckyOder = luckyOrderOpt.get(); log.info("有空闲车辆 {} 订单 {}", luckyOder.getOrderNumber(), orderNo); XpVehicle xpVehicle = xpVehicleClient.queryById(luckyOder.getVehicleId()).getData(); // 设置路线信息 RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); routeAndFareDto.setDestination(userPostion); routeAndFareDto.setOrigin(new LonLatDto(luckyOder.getEndLon(),luckyOder.getEndLat())); RouteVo routeToOrigin = xpMapClient.getDistanceAndDuration(routeAndFareDto).getData(); Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(luckyOder.getAppUserId().toString())); RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class); routeToOrigin.getPolyline().addAll(0, routeRemain.getPolyline()); routeToOrigin.setDuration(routeToOrigin.getDuration() + routeRemain.getDuration()); routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance()); //此处找到车后先不忙给车推送接单消息,先修改订单上的车辆信息 xpOrder.setVehicleId(xpVehicle.getId()); xpOrder.setAcceptanceTime(LocalDateTime.now()); xpOrder.setStatus(2); xpOrderClient.updateOrder(xpOrder); // PushOrderDto pushOrderDto = buildPushOrderDto(xpOrder); // pushOrderDto.setVin(xpVehicle.getVehicleVin()); // pushOrderDto.setTaskId(xpOrder.getXpuTaskId()); // pushOrderDto.setChainSingle(true); // // 订单流转 // orderMissionClient.pushOrder(pushOrderDto); JSONObject jsonObject = new JSONObject(); jsonObject.put("orderId", xpOrder.getId()); jsonObject.put("endLongitude", xpOrder.getEndLat()); jsonObject.put("endLatitude", xpOrder.getEndLat()); redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString()); redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), routeToOrigin); redisService.removeByPattern(quoteName,xpOrder.getOrderNumber()); log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); break; } } return false; } private static PushOrderDto buildPushOrderDto(XpOrder xpOrder) { PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setStartLatitude(xpOrder.getStartLat()); pushOrderDto.setStartLongitude(xpOrder.getStartLon()); pushOrderDto.setEndLatitude(xpOrder.getEndLat()); pushOrderDto.setEndLongitude(xpOrder.getEndLon()); pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); return pushOrderDto; } private boolean isClose(XpOrder xpOrder,RouteAndFareDto routeAndFareDto) { LonLatDto lonLatDto = new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat()); routeAndFareDto.setOrigin(lonLatDto); return xpMapClient.getDistanceAndDuration(routeAndFareDto).getData().getDistance() < 800; } @Resource private MongoTemplate mongoTemplate; /** * 重新改派 * 1.优化好点 做个倒计时的异步改派多次 * @param count 轮数 * @param uid 用户id * @param longitude 经度 * @param latitude 纬度 * @param orderNo 订单号 */ @SneakyThrows public XpOrderReassign reassignPushOrder(int count, String uid, Double longitude, Double latitude, String orderNo) { log.info("进入推单环环节"); if (count == 0) { count = 1; } // 订单状态 R xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { return null; } // List notDrive = new ArrayList(){{ //未行驶的情况下订单故障状态点 status=2、3、4、5 // add(OrderStatusEnum.READY_DEPART.getCode());add(OrderStatusEnum.PICK_UP.getCode()); // add(OrderStatusEnum.PICK_UP_GUESTS.getCode());add(OrderStatusEnum.PASSENGER_BOARDED.getCode()); // }}; if (xpOrderR.getData().getStatus() != 1) { return null; } XpOrder data = xpOrderR.getData(); XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); XpOrderReassign entity = new XpOrderReassign(data.getId(),data.getVehicleId(),data.getFleetId(),longitude,latitude,"接驾故障"); entity.setIsComplete(false); entity.setAppUserId(Long.valueOf(uid)); // 根据城市编码获取 定向服务设置的车辆 List targetedServiceVehicleVinList = xpTargetedServiceService.findSetVehicleVinByUserIdAndCityCode(data.getAppUserId(), data.getCityCode()); //循环找车 for (int i = 0; i < count; i++) { log.info("进入找车环节"); List positionList = vehiclePositionService.findAvailableVehiclesNearby(longitude, latitude, xpTradingStrategy.getOnePushDistance(), xpTradingStrategy.getSimultaneouslyOrderCount()); // 获取车辆的区域信息 if (positionList.isEmpty()) { log.info("没有找到空闲车辆 {},尝试连环派单给即将服务结束的车辆", orderNo); // 查询状态为1的车辆vin Set vinList = positionList.stream().map(VehiclePosition::getVin).collect(Collectors.toSet()); R> servingVehicles = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(data.getFleetId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount(),1)); if (servingVehicles.getCode() != 200) { continue; } LonLatDto userPosition = new LonLatDto(data.getStartLon(), data.getStartLat());//人的位置 XpTradingStrategyDetailVO strategyDetailVO = tradingStrategyClient.queryById().getData(); Integer distanceRegardAsEnding = strategyDetailVO.getDistanceRegardAsEnding(); Integer timeRegardAsEnding = strategyDetailVO.getTimeRegardAsEnding(); Integer backupPower = strategyDetailVO.getBackupPower(); Integer destToPassenger = strategyDetailVO.getDestToPassenger(); Integer endingTimeToUseTime = strategyDetailVO.getEndingTimeToUseTime(); LocalDateTime rideTime = data.getRideTime(); LocalDateTime now = LocalDateTime.now(); Optional luckyOrderOpt = servingVehicles.getData().stream() //获取位置 .map(vin -> mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class)) .map(VehiclePosition::getOrderId) .map(xpOrderClient::queryOrderById) .filter(R::isSuccess) .map(R::getData) .filter(o -> { XpVehicle xpVehicle = xpVehicleClient.queryById(o.getVehicleId()).getData(); Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(o.getAppUserId().toString())); RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class); if (routeRemain.getDuration() / 60 > timeRegardAsEnding) { return false; } if (routeRemain.getDistance() > distanceRegardAsEnding) { return false; } if (routeRemain.getDuration() / 60 > timeRegardAsEnding) { return false; } RouteAndFareDto next = new RouteAndFareDto(); next.setOrigin(new LonLatDto(o.getStartLon(),o.getStartLat())); next.setDestination(new LonLatDto(o.getEndLon(),o.getEndLat())); RouteVo route = xpMapClient.getDistanceAndDuration(next).getData(); if (route.getDistance() > backupPower + xpVehicle.getMileageRange()) return false; return routeRemain.getDistance() < destToPassenger || now.plusSeconds(routeRemain.getDuration()) .plusMinutes(endingTimeToUseTime) .isBefore(rideTime); }) .findAny(); if (luckyOrderOpt.isPresent()) { XpOrder luckyOder = luckyOrderOpt.get(); log.info("有空闲车辆 {} 订单 {}", luckyOder.getOrderNumber(), orderNo); XpVehicle xpVehicle = xpVehicleClient.queryById(luckyOder.getVehicleId()).getData(); // 设置路线信息 RouteAndFareDto pickUpRoute = new RouteAndFareDto(); pickUpRoute.setDestination(userPosition); pickUpRoute.setOrigin(new LonLatDto(luckyOder.getEndLon(),luckyOder.getEndLat())); RouteVo routeToOrigin = xpMapClient.getDistanceAndDuration(pickUpRoute).getData(); Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(luckyOder.getAppUserId().toString())); RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class); routeToOrigin.getPolyline().addAll(0, routeRemain.getPolyline()); routeToOrigin.setDuration(routeToOrigin.getDuration() + routeRemain.getDuration()); routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance()); JSONObject jsonObject = new JSONObject(); jsonObject.put("orderId", data.getId()); jsonObject.put("endLongitude", data.getEndLat()); jsonObject.put("endLatitude", data.getEndLat()); redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString()); redisService.setCacheObject(CacheConstants.navigationStart(data.getAppUserId().toString()), routeToOrigin); break; } } // 直接派单 定义一个锁来锁定车辆 VehiclePosition vehiclePosition = positionList.get(0); if(CollUtil.isNotEmpty(targetedServiceVehicleVinList)){//定向服务获取的车 for (VehiclePosition position : positionList) { if(targetedServiceVehicleVinList.contains(position.getVin())){ vehiclePosition = position; break; } } } String vehicleVin = vehiclePosition.getVin(); RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePosition.getVin()); lock.lock(10, TimeUnit.SECONDS); try { // 查询车辆状态 R vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if (vehicleR.getCode() != 200) { continue; } XpVehicle vehicleId1 = vehicleR.getData(); if (vehicleId1.getStatus() != 1 || vehicleId1.getState() != 0) { lock.unlock(); continue; } // 关闭巡游单子 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin()); if (stringR == null || stringR.getData() == null) { log.info("关闭巡游单子失败"); continue; } XpCruiseOrder cruiseOrder = stringR.getData(); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setStartTaskId(data.getXpuStartTaskId()); pushOrderDto.setEndTaskId(data.getXpuEndTaskId()); pushOrderDto.setVin(vehiclePosition.getVin()); pushOrderDto.setOrderId(data.getId().toString()); pushOrderDto.setStartLatitude(data.getStartLat()); pushOrderDto.setStartLongitude(data.getStartLon()); pushOrderDto.setEndLatitude(data.getEndLat()); pushOrderDto.setEndLongitude(data.getEndLon()); pushOrderDto.setEndPoiName(data.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); entity.setNewVehicleId(vehicleId1.getId()); entity.setNewFleetId(vehicleId1.getFleetId()); entity.setIsComplete(true); // //接单成功 将 修改 订单的状态=1 ( 状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成) // orderCarStatus = true; xpOrderClient.updateOrderStatus(data.getId(), OrderStatusEnum.PENDING_ORDER.getCode(), false); redisService.setCacheObject("ORDER_STATUS:" + data.getId(), OrderStatusEnum.PENDING_ORDER.getCode(), 24L, TimeUnit.HOURS); break; } catch (Exception e) { throw new RuntimeException(e); } finally { lock.unlock(); } } //保存改派记录 return entity; } }