| | |
| | | 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.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | 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.feignClient.pushMessage.XpPushMessageClient; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; |
| | | import com.xiaopeng.api.model.operation.XpElectronicFence; |
| | | import com.xiaopeng.api.model.operation.XpTargetedServiceVehicle; |
| | | import com.xiaopeng.api.model.operation.XpTradingStrategy; |
| | | import com.xiaopeng.api.model.operation.XpTradingStrategyPush; |
| | | 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.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.core.enums.PushMessageTypeEnum; |
| | | import com.xiaopeng.common.core.utils.SensitiveDataCryptoUtil; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | 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.IXpElectronicFenceAreaService; |
| | | import com.xiaopeng.operation.service.IXpTradingStrategyService; |
| | | import com.xiaopeng.operation.service.UidVinPriorityMatcher; |
| | | import com.xiaopeng.operation.service.XpPointService; |
| | | 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 javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneOffset; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.concurrent.LinkedBlockingQueue; |
| | | import java.util.concurrent.ThreadPoolExecutor; |
| | |
| | | @Slf4j |
| | | @Component |
| | | public class TaskOrderUtil { |
| | | @Resource |
| | | private XpTargetedServiceService xpTargetedServiceService; |
| | | |
| | | @Resource |
| | | private XpTargetedServiceVehicleService xpTargetedServiceVehicleService; |
| | | |
| | | @Resource |
| | | private RedisService redisService; |
| | |
| | | |
| | | @Resource |
| | | private IXpTradingStrategyService xpTradingStrategyService; |
| | | |
| | | @Resource |
| | | private IXpTradingStrategyPushService xpTradingStrategyPushService; |
| | | |
| | | @Resource |
| | | private XpCruiseOrderClient xpCruiseOrderClient; |
| | |
| | | @Resource |
| | | private XpAppUserCouponClient xpAppUserCouponClient; |
| | | |
| | | @Resource |
| | | private OfficialPartnerUtil officialPartnerUtil; |
| | | |
| | | |
| | | // 自定义线程池 |
| | | private static final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); |
| | |
| | | |
| | | /** |
| | | * 5秒执行一次 |
| | | * 播单 |
| | | * 播单 在下单的时候会存一个 redis 队列 |
| | | */ |
| | | @Scheduled(cron = "0/5 * * * * ?") |
| | | public void taskOrder() { |
| | |
| | | // 状态改为处理中 |
| | | redisService.updateFirst(name, value); |
| | | threadPoolTaskExecutor.submit(() -> { |
| | | orderProcess(name, firstElement.toString()); |
| | | log.info("订单处理:{}", firstElement); |
| | | orderProcess(name, firstElement.toString(), false); |
| | | }); |
| | | }else{ |
| | | //判断订单状态,如果不是待接单,则将数据清除 |
| | | String orderId = split[0]; |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(Long.valueOf(orderId)).getData(); |
| | | if(xpOrder.getStatus() != OrderStatusEnum.PENDING_ORDER.getCode()){ |
| | | if(StringUtils.isNotEmpty((xpOrder.getQueueName()))){ |
| | | redisService.removeByPattern(xpOrder.getQueueName(), xpOrder.getOrderNumber()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 定向订单 |
| | | */ |
| | | @Scheduled(cron = "0/5 * * * * ?") |
| | | public void taskOrder_targeted() { |
| | | System.out.println("5秒执行一次"); |
| | | Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID); |
| | | for (String name : quoteMatchName) { |
| | | String firstElement = redisService.getFirstElement(name); |
| | | if (firstElement != null) { |
| | | String[] split = firstElement.toString().split("_"); |
| | | // 如果未处理 创建新任务 |
| | | if (split[2].equals("0")) { |
| | | String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7] + "_" + split[8]; |
| | | // 状态改为处理中 |
| | | redisService.updateFirst(name, value); |
| | | threadPoolTaskExecutor.submit(() -> { |
| | | log.info("定向订单处理:{}", firstElement); |
| | | orderProcess(name, firstElement.toString(), true); |
| | | }); |
| | | }else{ |
| | | //判断订单状态,如果不是待接单,则将数据清除 |
| | | String orderId = split[0]; |
| | | XpOrder xpOrder = xpOrderClient.queryOrderById(Long.valueOf(orderId)).getData(); |
| | | if(xpOrder.getStatus() != OrderStatusEnum.PENDING_ORDER.getCode()){ |
| | | if(StringUtils.isNotEmpty(xpOrder.getQueueName())){ |
| | | redisService.removeByPattern(xpOrder.getQueueName(), xpOrder.getOrderNumber()); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | |
| | | * @param quoteName 队列名称 |
| | | * @param firstElement 队列第一个元素 |
| | | */ |
| | | private void orderProcess(String quoteName, String firstElement) { |
| | | private void orderProcess(String quoteName, String firstElement, Boolean isTargetedService) { |
| | | XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); |
| | | String orderId = firstElement.split("_")[0]; |
| | | String lonLat = firstElement.split("_")[1]; |
| | |
| | | // 经纬度 |
| | | String[] split = lonLat.split(","); |
| | | |
| | | //查询当前时段是不是特殊推单时段 |
| | | List<XpTradingStrategyPush> tradingStrategyId = xpTradingStrategyPushService.list(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", xpTradingStrategy)); |
| | | long now = Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm"))); |
| | | XpTradingStrategyPush xpTradingStrategyPush = tradingStrategyId.stream().filter(item -> { |
| | | long start = Long.parseLong(item.getStartTime().replace(":", "")); |
| | | long end = Long.parseLong(item.getEndTime().replace(":", "")); |
| | | return now >= start && now < end; |
| | | }).findFirst().orElse(null); |
| | | |
| | | |
| | | // 5轮找车辆 |
| | | //每次查找车辆推单后的等待秒数 |
| | | int sleepTime = 3; |
| | | Integer onePushTime = xpTradingStrategy.getOnePushTime(); |
| | | Double onePushDistance = xpTradingStrategy.getOnePushDistance(); |
| | | Integer onePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushTime() : xpTradingStrategy.getOnePushTime(); |
| | | Double onePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushDistance() : xpTradingStrategy.getOnePushDistance(); |
| | | int count = onePushTime / sleepTime; |
| | | // 第一轮推单 |
| | | log.info("开始第一轮推单 {}", orderNo); |
| | | Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule); |
| | | Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule, isTargetedService); |
| | | if(processed){ |
| | | log.info("订单推送成功 {}", orderNo); |
| | | return; |
| | | } |
| | | // 第二轮推单 |
| | | Integer twoPushTime = xpTradingStrategy.getTwoPushTime(); |
| | | Double twoPushDistance = xpTradingStrategy.getTwoPushDistance(); |
| | | Integer twoPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushTime() : xpTradingStrategy.getTwoPushTime(); |
| | | Double twoPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushDistance() : xpTradingStrategy.getTwoPushDistance(); |
| | | count = twoPushTime / sleepTime; |
| | | log.info("开始第二轮推单 {}", orderNo); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule, isTargetedService); |
| | | if(processed){ |
| | | log.info("订单推送成功 {}", orderNo); |
| | | return; |
| | | } |
| | | |
| | | // 第三轮推单 |
| | | Integer threePushTime = xpTradingStrategy.getThreePushTime(); |
| | | Double threePushDistance = xpTradingStrategy.getThreePushDistance(); |
| | | Integer threePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushTime() : xpTradingStrategy.getThreePushTime(); |
| | | Double threePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushDistance() : xpTradingStrategy.getThreePushDistance(); |
| | | count = threePushTime / sleepTime; |
| | | log.info("开始第三轮推单 {}", orderNo); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule, isTargetedService); |
| | | if(processed){ |
| | | log.info("订单推送成功 {}", orderNo); |
| | | return; |
| | | } |
| | | |
| | | // 第四轮推单 |
| | | Integer fourPushTime = xpTradingStrategy.getFourPushTime(); |
| | | Double fourPushDistance = xpTradingStrategy.getFourPushDistance(); |
| | | Integer fourPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushTime() : xpTradingStrategy.getFourPushTime(); |
| | | Double fourPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushDistance() : xpTradingStrategy.getFourPushDistance(); |
| | | count = fourPushTime / sleepTime; |
| | | log.info("开始第四轮推单 {}", orderNo); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule, isTargetedService); |
| | | if(processed){ |
| | | log.info("订单推送成功 {}", orderNo); |
| | | return; |
| | | } |
| | | |
| | | // 第五轮推单 |
| | | Integer fivePushTime = xpTradingStrategy.getFivePushTime(); |
| | | Double fivePushDistance = xpTradingStrategy.getFivePushDistance(); |
| | | Integer fivePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushTime() : xpTradingStrategy.getFivePushTime(); |
| | | Double fivePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushDistance() : xpTradingStrategy.getFivePushDistance(); |
| | | count = fivePushTime / sleepTime; |
| | | log.info("开始第五轮推单 {}", orderNo); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule); |
| | | processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule, isTargetedService); |
| | | if(processed){ |
| | | log.info("订单推送成功 {}", orderNo); |
| | | return; |
| | |
| | | if (xpOrderR.getCode() == 200) { |
| | | XpOrder xpOrder = xpOrderR.getData(); |
| | | if (xpOrder.getStatus() == 1) { |
| | | log.info("五轮推单结束,无车辆接单,执行取消订单 {}", orderNo); |
| | | xpOrderClient.cancelOrder(orderId); |
| | | log.info("五轮推单结束,无车辆接单,执行取消订单 {}", orderNo); |
| | | //推送订单状态给乘客 |
| | | SendMessageDTO dto = new SendMessageDTO(); |
| | | dto.setAppUserId(xpOrder.getAppUserId().toString()); |
| | |
| | | } |
| | | }); |
| | | } |
| | | //将订单从队列中移除 |
| | | log.info("五轮推单结束,无车辆接单,执行队列移除订单 {}", orderNo); |
| | | redisService.popFirstElement(quoteName); |
| | | } |
| | | } |
| | | |
| | |
| | | * @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) { |
| | | 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, Boolean isTargetedService) { |
| | | log.info("进入推单环节 单号 {}", orderNo); |
| | | if (count == 0) { |
| | | count = 1; |
| | |
| | | } |
| | | XpOrder xpOrder = xpOrderR.getData(); |
| | | if (xpOrder.getStatus() == 0) { |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | log.info("订单已取消,退出退单逻辑 {}", orderNo); |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | // 找出围栏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<XpVehicle> 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(); |
| | | //判断当前车辆是否在禁派单车辆内 |
| | | String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId()); |
| | | List<String> strings = new ArrayList<>(); |
| | | if(null != cacheList){ |
| | | strings = JSON.parseArray(cacheList, String.class); |
| | | } |
| | | log.info("[人车订单绑定测试] 二次校验-车辆状态: operatingStatus={}, state={}, vehicleType={}, vin={}", |
| | | vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType(), priorityVin); |
| | | if (vehicle.getOperatingStatus() == 1 && vehicle.getState() == 0 && vehicle.getVehicleType() != 1 && !strings.contains(vehicle.getVehicleVin())) { |
| | | log.info("[人车订单绑定测试] 二次校验-车辆状态通过(空闲), 开始校验订单状态, orderNo={}", orderNo); |
| | | // 二次校验订单状态 |
| | | R<XpOrder> 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); |
| | | // 下发XPU命令 |
| | | PushOrderDto pushOrderDto = new PushOrderDto(); |
| | | pushOrderDto.setVin(priorityVin); |
| | | pushOrderDto.setOrderId(orderCheck.getData().getId().toString()); |
| | | pushOrderDto.setStartTaskId(orderCheck.getData().getXpuStartTaskId()); |
| | | pushOrderDto.setEndTaskId(orderCheck.getData().getXpuEndTaskId()); |
| | | pushOrderDto.setStartWaypointId(orderCheck.getData().getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(orderCheck.getData().getEndPointId()); |
| | | 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); |
| | | 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); |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | 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); |
| | | } |
| | | // ===== 新增结束 ===== |
| | | |
| | | for (int i = 0; i < count; i++) { |
| | | //等到sleepTime秒钟 |
| | | Thread.sleep(sleepTime * 1000); |
| | | // 根据距离找车 |
| | | // 车多则根据配置找具体车数量 根据距离最近 |
| | | // 更改 暂不限制数量 |
| | | List<VehiclePosition> positionList = vehiclePositionService.findAvailableVehiclesNearby(Double.parseDouble(split[0]), Double.parseDouble(split[1]), pushDistance, xpTradingStrategy.getSimultaneouslyOrderCount()); |
| | | log.info("根据距离找车 {} 距离 {}KM 经度 {} 维度 {} 查找结果 {} 单号 {}", orderNo, pushDistance, split[0], split[1], JSON.toJSONString(positionList), orderNo); |
| | | // 获取车辆的区域信息 |
| | | if (positionList.isEmpty()) { |
| | | continue; |
| | | } |
| | | Set<String> vinList = positionList.stream().map(VehiclePosition::getVin).collect(Collectors.toSet()); |
| | | |
| | | //判断当前车辆是否在禁派单车辆内 |
| | | String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId()); |
| | | if(Objects.nonNull(cacheList)){ |
| | | List<String> strings = JSON.parseArray(cacheList, String.class); |
| | | Set<String> vins = new HashSet<>(); |
| | | for (String s : vinList) { |
| | | if (!strings.contains(s)) { |
| | | vins.add(s); |
| | | } |
| | | } |
| | | vinList = vins; |
| | | } |
| | | |
| | | // 获取车辆的信息 筛选出可用车辆,定向服务的车辆排除 |
| | | R<List<String>> vehiclePositionVos = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount())); |
| | | log.info("筛选可用车辆结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); |
| | | List<String> vehicleVinByTargetedService = xpTargetedServiceVehicleService.getVehicleVinByTargetedService(xpOrderR.getData().getCityCode()); |
| | | if(!isTargetedService){ |
| | | vehiclePositionVos.getData().removeAll(vehicleVinByTargetedService); |
| | | log.info("剔除定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); |
| | | }else{ |
| | | vehiclePositionVos.setData(vehicleVinByTargetedService); |
| | | log.info("查找定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); |
| | | } |
| | | if (vehiclePositionVos.getCode() != 200) { |
| | | continue; |
| | | } |
| | | List<VehiclePositionVo> availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class); |
| | | List<String> data = vehiclePositionVos.getData(); |
| | | |
| | | // 找出符合条件的 |
| | | availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> data.contains(e.getVin())).collect(Collectors.toList()); |
| | | |
| | | 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<Integer> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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<RouteVo> 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); |
| | | |
| | | RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin()); |
| | | lock.lock(10, TimeUnit.SECONDS); |
| | | log.info("队列 {} 车辆 {} 单号 {}", quoteName, vehiclePositionVo.getVin(), orderNo); |
| | | try { |
| | | R<XpVehicle> vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin()); |
| | | if (vehiclePositionR.getCode() == 200) { |
| | | XpVehicle vehiclePosition = vehiclePositionR.getData(); |
| | | log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo); |
| | | log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getState(), orderNo); |
| | | |
| | | String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehiclePosition.getVehicleVin()); |
| | | // 再次查询一下订单 看是否取消 |
| | | xpOrder = xpOrderClient.queryOrderByOrderNo(orderNo).getData(); |
| | | if (xpOrder.getStatus() == 1) { |
| | | //所有条件满足,走正常派单,不满足走后面的连环派单 |
| | | if (vehiclePosition.getOperatingStatus() == 1 && vehiclePosition.getState() == 0 && vehiclePosition.getVehicleType() == 2) { |
| | | //非合作商的车辆需要处理巡游单 |
| | | if(null == vehiclePosition.getOfficialPartnerId()){ |
| | | // 关闭巡游单子 |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin); |
| | | if (stringR != null && stringR.getCode() == 200) { |
| | | log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo); |
| | | XpCruiseOrder cruiseOrder = stringR.getData(); |
| | | // 下发命令 |
| | | PushOrderDto pushOrderDto = new PushOrderDto(); |
| | | pushOrderDto.setVin(vin); |
| | | pushOrderDto.setOrderId(xpOrder.getId().toString()); |
| | | pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId()); |
| | | pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); |
| | | pushOrderDto.setStartWaypointId(xpOrder.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(xpOrder.getEndPointId()); |
| | | 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); |
| | | if(null != cruiseOrder){ |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | } |
| | | pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); |
| | | // 调用推送服务 orderId + carVin |
| | | orderMissionClient.pushOrder(pushOrderDto); |
| | | log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo); |
| | | } |
| | | }else { |
| | | //流量接入-接单推送 合作商的车辆需要调用合作商的订单通知接口 |
| | | officialPartnerUtil.pushNewOrder(vehiclePosition.getOfficialPartnerId(), xpOrder); |
| | | } |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | 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<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); |
| | | if (vehicleR.getCode() == 200) { |
| | | XpVehicle vehicleId1 = vehicleR.getData(); |
| | | log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo); |
| | | log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo); |
| | | |
| | | // 再次查询一下订单 看是否取消 |
| | | xpOrder = xpOrderClient.queryOrderByOrderNo(orderNo).getData(); |
| | | if (xpOrder.getStatus() == 1) { |
| | | // 所有条件满足走正常派单,不满足走循环派单 |
| | | if (vehicleId1.getOperatingStatus() == 1 && vehicleId1.getState() == 0 && vehicleId1.getVehicleType() == 2) { |
| | | if(null == vehicleId1.getOfficialPartnerId()){ |
| | | // 关闭巡游单子 |
| | | String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicleId1.getVehicleVin()); |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin); |
| | | if (stringR != null && stringR.getCode() == 200) { |
| | | log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo); |
| | | XpCruiseOrder cruiseOrder = stringR.getData(); |
| | | PushOrderDto pushOrderDto = new PushOrderDto(); |
| | | pushOrderDto.setVin(vehiclePosition.getVin()); |
| | | pushOrderDto.setOrderId(xpOrder.getId().toString()); |
| | | pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId()); |
| | | pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); |
| | | pushOrderDto.setStartWaypointId(xpOrder.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(xpOrder.getEndPointId()); |
| | | 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); |
| | | if(null != cruiseOrder){ |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | } |
| | | pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); |
| | | // 调用推送服务 orderId + carVin |
| | | orderMissionClient.pushOrder(pushOrderDto); |
| | | } |
| | | }else { |
| | | //流量接入-接单推送 合作商的车辆需要调用合作商的订单通知接口 |
| | | officialPartnerUtil.pushNewOrder(vehicleId1.getOfficialPartnerId(), xpOrder); |
| | | } |
| | | log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber()); |
| | | |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | } |
| | | |
| | | log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | log.info("没有找到空闲车辆 {},尝试连环派单给即将服务结束的车辆", orderNo); |
| | | // 查询状态为1的车辆vin |
| | | R<List<String>> servingVehicles = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount(),1)); |
| | | if (servingVehicles.getCode() != 200) { |
| | | continue; |
| | | } |
| | | log.info("连环派单查询车辆结果 {} {}", orderNo, JSON.toJSONString(servingVehicles.getData())); |
| | | if(!isTargetedService){ |
| | | servingVehicles.getData().removeAll(vehicleVinByTargetedService); |
| | | log.info("连环派单剔除定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(servingVehicles), orderNo); |
| | | }else{ |
| | | servingVehicles.setData(vehicleVinByTargetedService); |
| | | log.info("连环派单查找定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(servingVehicles), orderNo); |
| | | } |
| | | |
| | | XpTradingStrategyDetailVO strategyDetailVO = tradingStrategyClient.queryById().getData(); |
| | | log.info("连环排查推单逻辑 {} {}", orderNo, JSON.toJSONString(strategyDetailVO)); |
| | | Integer distanceRegardAsEnding = strategyDetailVO.getDistanceRegardAsEnding(); |
| | | Integer timeRegardAsEnding = strategyDetailVO.getTimeRegardAsEnding(); |
| | | |
| | | Integer backupPower = strategyDetailVO.getBackupPower(); |
| | | Integer destToPassenger = strategyDetailVO.getDestToPassenger(); |
| | | Integer endingTimeToUseTime = strategyDetailVO.getEndingTimeToUseTime(); |
| | | |
| | | for (String vin : servingVehicles.getData()) { |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class); |
| | | if(null == vehiclePosition){ |
| | | log.info("连环派单 {} 车辆查询定位数据失败 {}", vin, orderNo); |
| | | continue; |
| | | } |
| | | XpOrder xpOrder1 = xpOrderClient.queryOrderById(vehiclePosition.getOrderId()).getData(); |
| | | String json = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder1.getId().toString())); |
| | | if (StringUtils.isNotEmpty(json)){ |
| | | log.info("车辆已经有连环订单 {} 单号 {}", vin, orderNo); |
| | | continue; |
| | | } |
| | | Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(xpOrder1.getAppUserId().toString())); |
| | | RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class); |
| | | //距离和时间只要有一个满足条件就达到候选对象 |
| | | if (routeRemain.getDuration() > timeRegardAsEnding * 60 && routeRemain.getDistance() > distanceRegardAsEnding * 1000) { |
| | | log.info("连环派单 {} 车辆订单结束时间不满足条件 {} 秒 {} 米 {}", vin, routeRemain.getDuration(), routeRemain.getDistance(), orderNo); |
| | | continue; |
| | | } |
| | | |
| | | //剩余里程》=下一单预估里程+50 |
| | | //预估接驾行程+送驾行程 |
| | | RouteAndFareDto next = new RouteAndFareDto(); |
| | | next.setOrigin(new LonLatDto(xpOrder1.getEndLon(),xpOrder1.getEndLat())); |
| | | next.setDestination(new LonLatDto(xpOrder.getStartLon(),xpOrder.getStartLat())); |
| | | RouteVo route = xpMapClient.getDistanceAndDuration(next).getData(); |
| | | Object new_cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(xpOrder.getAppUserId().toString())); |
| | | RouteVo new_routeRemain = JSON.parseObject(new_cacheObject.toString(), RouteVo.class); |
| | | //总续航里程 米 |
| | | long xh = new_routeRemain.getDistance() + route.getDistance() + backupPower * 1000; |
| | | if(vehiclePosition.getMileageRange() * 1000 < xh){ |
| | | log.info("连环派单 {} 车辆剩余续航不满足派车条件 {} 米 {}", vin, xh, orderNo); |
| | | continue; |
| | | } |
| | | |
| | | //下一单的起点距离本单终点小于X公里,或者下一单的用车时间与本单的预计结束时间偏差小于X分钟 |
| | | //上一单的预估结束时间 |
| | | LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(routeRemain.getDuration()); |
| | | //上一单预估结束时间与本单用车时间差 秒 |
| | | long time = localDateTime.toEpochSecond(ZoneOffset.of("+8")) - xpOrder1.getCreateTime().toEpochSecond(ZoneOffset.of("+8")); |
| | | if(route.getDistance() <= destToPassenger * 1000 || time <= endingTimeToUseTime * 60){ |
| | | log.info("连环派单 {} 找到满足条件的车辆 {} 距离 {} 时间 {}", orderNo, vin, route.getDistance(), time); |
| | | log.info("上一单终点与当前订单起点距离 {} 米 {}", route.getDistance(), orderNo); |
| | | log.info("当前订单用车时间与上一单预估结束时间偏差 {} 秒 {}", time, orderNo); |
| | | // 设置接驾导航数据 |
| | | //将上一单的剩余导航添加到接驾导航中 |
| | | route.getPolyline().addAll(0, routeRemain.getPolyline()); |
| | | route.setDuration(route.getDuration() + routeRemain.getDuration()); |
| | | route.setDistance(route.getDistance() + routeRemain.getDistance()); |
| | | |
| | | //此处找到车后先不忙给车推送接单消息,先修改订单上的车辆信息 |
| | | xpOrder.setVehicleId(xpOrder1.getVehicleId()); |
| | | xpOrder.setAcceptanceTime(LocalDateTime.now()); |
| | | xpOrder.setStatus(2); |
| | | xpOrderClient.updateOrder(xpOrder); |
| | | log.info("连环派单 {} 修改订单状态为接单成功 {}", orderNo, xpOrder.getId()); |
| | | |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderId", xpOrder.getId()); |
| | | jsonObject.put("endLongitude", xpOrder.getEndLon()); |
| | | jsonObject.put("endLatitude", xpOrder.getEndLat()); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(xpOrder1.getId().toString()), jsonObject.toJSONString()); |
| | | redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), JSON.toJSONString(route)); |
| | | |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName,xpOrder.getOrderNumber()); |
| | | } |
| | | log.info("连环派单 {} 设置下一单接驾导航数据 {}", orderNo, JSON.toJSONString(route)); |
| | | |
| | | //构建推送消息 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | Map<String, Object> content = new HashMap<>(); |
| | | content.put("orderId", xpOrder.getId().toString()); |
| | | content.put("status", 2); |
| | | params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc()); |
| | | params.put("content", JSONObject.toJSONString(content)); |
| | | params.put("timestamp", System.currentTimeMillis() + ""); |
| | | String message = JSONObject.toJSONString(params); |
| | | SendMessageDTO dto1 = new SendMessageDTO(); |
| | | dto1.setAppUserId(xpOrder.getAppUserId() + ""); |
| | | dto1.setMessage(message); |
| | | R<String> stringR = xpPushMessageClient.sendStatus(dto1); |
| | | |
| | | //推送失败,重试3次 |
| | | if (stringR.getCode() != Constants.SUCCESS) { |
| | | ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); |
| | | XpOrder finalXpOrder = xpOrder; |
| | | executor.execute(() -> { |
| | | for (int j = 0; j < 3; j++) { |
| | | R<String> stringR1 = xpPushMessageClient.sendStatus(dto1); |
| | | if (stringR1.getCode() == Constants.SUCCESS) { |
| | | break; |
| | | } |
| | | try { |
| | | Thread.sleep(1000); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | log.info("推送订单状态消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(dto1), finalXpOrder.getOrderNumber()); |
| | | } |
| | | }); |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 定向服务订单处理 |
| | | * @param quoteName 队列名称 |
| | | * @param count 轮数 |
| | | * @param uid |
| | | * @param split 经纬度 |
| | | * @param orderNo 订单号 |
| | | * @param xpTradingStrategy 规则 |
| | | */ |
| | | @SneakyThrows |
| | | private Boolean processPushSpOrder(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<XpOrder> 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) { |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | } |
| | | |
| | | } |
| | | |
| | | // 找出围栏id |
| | |
| | | pushOrderDto.setStartTaskId(orderCheck.getData().getXpuStartTaskId()); |
| | | pushOrderDto.setEndTaskId(orderCheck.getData().getXpuEndTaskId()); |
| | | pushOrderDto.setOrderId(orderCheck.getData().getId().toString()); |
| | | pushOrderDto.setStartWaypointId(orderCheck.getData().getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(orderCheck.getData().getEndPointId()); |
| | | pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat()); |
| | | pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon()); |
| | | pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat()); |
| | |
| | | pushOrderDto.setEndPoiName(orderCheck.getData().getEndPointName()); |
| | | pushOrderDto.setOrderType(OrderType.USER_ORDER); |
| | | pushOrderDto.setStage(1); |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | if(null != cruiseOrder){ |
| | | 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); |
| | | |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, orderNo); |
| | | } |
| | | |
| | | return true; |
| | | } else { |
| | | log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo); |
| | |
| | | log.info("[人车订单绑定测试] 总开关未开启(enabled=false), 跳过优先匹配, uid={}, orderNo={}", uid, orderNo); |
| | | } |
| | | // ===== 新增结束 ===== |
| | | |
| | | //根据 用户id 和 城市编码 查询 定向服务的 车辆信息 |
| | | List<String> targetedServiceVehicleVinList = xpTargetedServiceService.findSetVehicleVinByUserIdAndCityCode(xpOrder.getAppUserId(), xpOrder.getCityCode()); |
| | | for (int i = 0; i < count; i++) { |
| | | //等到sleepTime秒钟 |
| | | Thread.sleep(sleepTime * 1000); |
| | |
| | | if (vehiclePositionVos.getCode() != 200) { |
| | | continue; |
| | | } |
| | | List<VehiclePositionVo> availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class); |
| | | List<String> data = vehiclePositionVos.getData(); |
| | | List<String> data = vehiclePositionVos.getData(); //指定区域的车 |
| | | // 计算交集:指定区域的车辆 与 定向服务车辆列表的交集 |
| | | if (targetedServiceVehicleVinList != null && !targetedServiceVehicleVinList.isEmpty() && data != null) { |
| | | Collection<String> newVehicleVinList = CollUtil.intersection(data,targetedServiceVehicleVinList); |
| | | if(CollUtil.isNotEmpty(newVehicleVinList)){ |
| | | data = (List<String>) newVehicleVinList; |
| | | } |
| | | } |
| | | |
| | | List<VehiclePositionVo> availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class); |
| | | // 找出符合条件的 |
| | | availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> data.contains(e.getVin())).collect(Collectors.toList()); |
| | | List<String> finalData = data; |
| | | availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> finalData.contains(e.getVin())).collect(Collectors.toList()); |
| | | // List<VehiclePositionVo> availableVehiclesNearby =vehiclePositionVos.getData(); |
| | | |
| | | if (!availableVehiclesNearby.isEmpty()) { |
| | |
| | | continue; |
| | | } |
| | | |
| | | |
| | | String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehiclePosition.getVehicleVin()); |
| | | // 关闭巡游单子 |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin()); |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin); |
| | | if (stringR == null || stringR.getCode() != 200) { |
| | | log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber()); |
| | | continue; |
| | |
| | | PushOrderDto pushOrderDto = new PushOrderDto(); |
| | | pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId()); |
| | | pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); |
| | | pushOrderDto.setVin(vehiclePosition.getVehicleVin()); |
| | | pushOrderDto.setVin(vin); |
| | | pushOrderDto.setOrderId(xpOrder.getId().toString()); |
| | | pushOrderDto.setStartWaypointId(xpOrder.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(xpOrder.getEndPointId()); |
| | | pushOrderDto.setStartLatitude(xpOrder.getStartLat()); |
| | | pushOrderDto.setStartLongitude(xpOrder.getStartLon()); |
| | | pushOrderDto.setEndLatitude(xpOrder.getEndLat()); |
| | |
| | | pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); |
| | | pushOrderDto.setOrderType(OrderType.USER_ORDER); |
| | | pushOrderDto.setStage(1); |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | if(null != cruiseOrder){ |
| | | 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()); |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | } |
| | | log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); |
| | | return true; |
| | | } catch (Exception e) { |
| | |
| | | continue; |
| | | } |
| | | XpVehicle vehicleId1 = vehicleR.getData(); |
| | | String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicleId1.getVehicleVin()); |
| | | log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo); |
| | | log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo); |
| | | if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) { |
| | |
| | | } |
| | | |
| | | // 关闭巡游单子 |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin()); |
| | | R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin); |
| | | if (stringR == null || stringR.getCode() != 200) { |
| | | log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber()); |
| | | continue; |
| | |
| | | pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId()); |
| | | pushOrderDto.setVin(vehiclePosition.getVin()); |
| | | pushOrderDto.setOrderId(xpOrder.getId().toString()); |
| | | pushOrderDto.setStartWaypointId(xpOrder.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(xpOrder.getEndPointId()); |
| | | pushOrderDto.setStartLatitude(xpOrder.getStartLat()); |
| | | pushOrderDto.setStartLongitude(xpOrder.getStartLon()); |
| | | pushOrderDto.setEndLatitude(xpOrder.getEndLat()); |
| | |
| | | pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); |
| | | pushOrderDto.setOrderType(OrderType.USER_ORDER); |
| | | pushOrderDto.setStage(1); |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | if(null != cruiseOrder){ |
| | | 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); |
| | | |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); |
| | | } |
| | | log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); |
| | | return true; |
| | | } catch (Exception e) { |
| | |
| | | // orderMissionClient.pushOrder(pushOrderDto); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderId", xpOrder.getId()); |
| | | jsonObject.put("endLongitude", xpOrder.getEndLat()); |
| | | jsonObject.put("endLongitude", xpOrder.getEndLon()); |
| | | 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()); |
| | | if(StringUtils.isNotEmpty(quoteName)){ |
| | | 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.setStartWaypointId(xpOrder.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(xpOrder.getEndPointId()); |
| | | pushOrderDto.setStartLatitude(xpOrder.getStartLat()); |
| | | pushOrderDto.setStartLongitude(xpOrder.getStartLon()); |
| | | pushOrderDto.setEndLatitude(xpOrder.getEndLat()); |
| | |
| | | XpOrderReassign entity = new XpOrderReassign(data.getId(),data.getVehicleId(),data.getFleetId(),longitude,latitude,"接驾故障"); |
| | | entity.setIsComplete(false); |
| | | entity.setAppUserId(Long.valueOf(uid)); |
| | | |
| | | // 根据城市编码获取 定向服务设置的车辆 |
| | | List<String> targetedServiceVehicleVinList = xpTargetedServiceService.findSetVehicleVinByUserIdAndCityCode(data.getAppUserId(), data.getCityCode()); |
| | | |
| | | //循环找车 |
| | | for (int i = 0; i < count; i++) { |
| | | log.info("进入找车环节"); |
| | |
| | | routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance()); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("orderId", data.getId()); |
| | | jsonObject.put("endLongitude", data.getEndLat()); |
| | | jsonObject.put("endLongitude", data.getEndLon()); |
| | | jsonObject.put("endLatitude", data.getEndLat()); |
| | | redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString()); |
| | | redisService.setCacheObject(CacheConstants.navigationStart(data.getAppUserId().toString()), routeToOrigin); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // 直接派单 定义一个锁来锁定车辆 |
| | | 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); |
| | |
| | | pushOrderDto.setEndTaskId(data.getXpuEndTaskId()); |
| | | pushOrderDto.setVin(vehiclePosition.getVin()); |
| | | pushOrderDto.setOrderId(data.getId().toString()); |
| | | pushOrderDto.setStartWaypointId(data.getStartPointId()); |
| | | pushOrderDto.setEndWaypointId(data.getEndPointId()); |
| | | pushOrderDto.setStartLatitude(data.getStartLat()); |
| | | pushOrderDto.setStartLongitude(data.getStartLon()); |
| | | pushOrderDto.setEndLatitude(data.getEndLat()); |
| | |
| | | pushOrderDto.setEndPoiName(data.getEndPointName()); |
| | | pushOrderDto.setOrderType(OrderType.USER_ORDER); |
| | | pushOrderDto.setStage(1); |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | if(null != cruiseOrder){ |
| | | pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId()); |
| | | pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId()); |
| | | } |
| | | pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask); |
| | | // 调用推送服务 orderId + carVin |
| | | orderMissionClient.pushOrder(pushOrderDto); |
| | |
| | | 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); |
| | | xpOrderClient.updateOrderStatus(data.getId(), OrderStatusEnum.PENDING_ORDER.getCode()); |
| | | redisService.setCacheObject("ORDER_STATUS:" + data.getId(), OrderStatusEnum.PENDING_ORDER.getCode(), 24L, TimeUnit.HOURS); |
| | | |
| | | break; |