| | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | @Override |
| | | public int batchCalculateMileageStats(Date statDate) { |
| | | try { |
| | | // 计算查询开始时间(7天前) |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(statDate); |
| | | calendar.add(Calendar.DAY_OF_MONTH, -7); |
| | | Date startTime = calendar.getTime(); |
| | | |
| | | // 查询所有活跃车辆 |
| | | List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(); |
| | | List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime); |
| | | |
| | | if (vehicleIds == null || vehicleIds.isEmpty()) { |
| | | logger.info("没有找到活跃车辆"); |
| | |
| | | } |
| | | } |
| | | |
| | | // 4. 查询该日期的任务时间区间,计算任务里程和非任务里程 |
| | | List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd); |
| | | |
| | | // 4. 计算任务里程和非任务里程(优化:优先使用task_id直接聚合) |
| | | BigDecimal taskMileage = BigDecimal.ZERO; |
| | | BigDecimal nonTaskMileage = BigDecimal.ZERO; |
| | | int taskCount = 0; // 任务数量 |
| | | |
| | | // 4.1 统计有task_id的分段数量 |
| | | int segmentsWithTask = 0; |
| | | for (VehicleGpsSegmentMileage segment : segments) { |
| | | Date segStart = segment.getSegmentStartTime(); |
| | | Date segEnd = segment.getSegmentEndTime(); |
| | | BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO; |
| | | if (segment.getTaskId() != null) { |
| | | segmentsWithTask++; |
| | | } |
| | | } |
| | | |
| | | // 4.2 如果大部分分段都有task_id,使用优化方案(直接按task_id聚合) |
| | | if (segmentsWithTask > segments.size() * 0.8) { |
| | | logger.debug("车辆ID: {} 日期: {} 使用优化方案:直接按task_id聚合({}个分段有task_id,占比{}%)", |
| | | vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size())); |
| | | |
| | | // 计算该分段与任务时段的重叠比例 |
| | | double taskRatio = calculateTaskOverlapRatio(segStart, segEnd, taskIntervals); |
| | | // 使用Set统计去重的任务ID数量 |
| | | Set<Long> uniqueTaskIds = new HashSet<>(); |
| | | |
| | | // 分摇里程 |
| | | BigDecimal taskDist = segDistance.multiply(BigDecimal.valueOf(taskRatio)); |
| | | BigDecimal nonTaskDist = segDistance.multiply(BigDecimal.valueOf(1 - taskRatio)); |
| | | // 直接按task_id分组聚合 |
| | | for (VehicleGpsSegmentMileage segment : segments) { |
| | | BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO; |
| | | |
| | | if (segment.getTaskId() != null) { |
| | | // 有任务ID,计入任务里程 |
| | | taskMileage = taskMileage.add(segDistance); |
| | | uniqueTaskIds.add(segment.getTaskId()); |
| | | } else { |
| | | // 没有任务ID,计入非任务里程 |
| | | nonTaskMileage = nonTaskMileage.add(segDistance); |
| | | } |
| | | } |
| | | |
| | | taskMileage = taskMileage.add(taskDist); |
| | | nonTaskMileage = nonTaskMileage.add(nonTaskDist); |
| | | // 设置去重后的任务数量 |
| | | taskCount = uniqueTaskIds.size(); |
| | | |
| | | } else { |
| | | // 4.3 降级方案:使用原有的时间重叠计算方式 |
| | | logger.debug("车辆ID: {} 日期: {} 使用降级方案:时间重叠计算(只有{}个分段有task_id,占比{}%)", |
| | | vehicleId, statDate, segmentsWithTask, (segmentsWithTask * 100.0 / segments.size())); |
| | | |
| | | List<TaskTimeInterval> taskIntervals = vehicleMileageStatsMapper.selectTaskTimeIntervals(vehicleId, dayStart, dayEnd); |
| | | |
| | | for (VehicleGpsSegmentMileage segment : segments) { |
| | | Date segStart = segment.getSegmentStartTime(); |
| | | Date segEnd = segment.getSegmentEndTime(); |
| | | BigDecimal segDistance = segment.getSegmentDistance() != null ? segment.getSegmentDistance() : BigDecimal.ZERO; |
| | | |
| | | // 计算该分段与任务时段的重叠比例 |
| | | double taskRatio = calculateTaskOverlapRatio(segStart, segEnd, taskIntervals); |
| | | |
| | | // 分摊里程 |
| | | BigDecimal taskDist = segDistance.multiply(BigDecimal.valueOf(taskRatio)); |
| | | BigDecimal nonTaskDist = segDistance.multiply(BigDecimal.valueOf(1 - taskRatio)); |
| | | |
| | | taskMileage = taskMileage.add(taskDist); |
| | | nonTaskMileage = nonTaskMileage.add(nonTaskDist); |
| | | } |
| | | |
| | | // 设置任务数量 |
| | | taskCount = taskIntervals == null ? 0 : taskIntervals.size(); |
| | | } |
| | | |
| | | // 计算任务里程占比 |
| | |
| | | stats.setNonTaskMileage(nonTaskMileage.setScale(2, RoundingMode.HALF_UP)); |
| | | stats.setTaskRatio(taskRatio); |
| | | stats.setGpsPointCount(totalGpsPoints); |
| | | stats.setTaskCount(taskIntervals == null ? 0 : taskIntervals.size()); |
| | | stats.setTaskCount(taskCount); |
| | | stats.setSegmentCount(segments.size()); |
| | | stats.setDataSource("segment"); // 标记数据来源为分段汇总 |
| | | |
| | |
| | | @Override |
| | | public int batchAggregateFromSegmentMileage(Date statDate) { |
| | | try { |
| | | // 计算查询开始时间(7天前) |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(statDate); |
| | | calendar.add(Calendar.DAY_OF_MONTH, -7); |
| | | Date startTime = calendar.getTime(); |
| | | |
| | | // 查询所有活跃车辆 |
| | | List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(); |
| | | List<Long> vehicleIds = vehicleGpsMapper.selectActiveVehicleIds(startTime); |
| | | |
| | | if (vehicleIds == null || vehicleIds.isEmpty()) { |
| | | logger.info("没有找到活跃车辆"); |