|
|
@ -5,10 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
|
|
import com.ruoyi.common.core.redis.RedisCache; |
|
|
|
import com.zc.business.constant.RedisKeyConstants; |
|
|
|
import com.zc.business.constant.StakeMarkConstant; |
|
|
|
import com.zc.business.domain.DcRoadSection; |
|
|
|
import com.zc.business.domain.DcTrafficMetricsData; |
|
|
|
import com.zc.business.domain.DcTrafficSectionData; |
|
|
|
import com.zc.business.domain.DcTrafficVolumeForecast; |
|
|
|
import com.zc.business.domain.*; |
|
|
|
import com.zc.business.enums.*; |
|
|
|
import com.zc.business.request.DcTrafficMetricsDataRequest; |
|
|
|
import com.zc.business.service.DcTrafficVolumeForecastService; |
|
|
@ -425,7 +422,7 @@ public class TrafficAnalysis { |
|
|
|
int stakeMark = dcTrafficSectionData.getStakeMark(); |
|
|
|
|
|
|
|
// 对于不拥堵的路段,累加之前计算的默认拥堵距离
|
|
|
|
if (!ChannelCongestionLevelEnum.isMediumOrSevereCongestion(averageSpeed) || dcTrafficSectionData.getTrafficVolume() == 0) { |
|
|
|
if (!ChannelCongestionLevelEnum.isMediumOrSevereCongestion(averageSpeed, dcTrafficSectionData.getTrafficVolume())) { |
|
|
|
totalCongestionDistance.addAndGet(defaultCongestionDistance); |
|
|
|
previousStakeMark = stakeMark; |
|
|
|
defaultCongestionDistance = 0; |
|
|
@ -441,6 +438,7 @@ public class TrafficAnalysis { |
|
|
|
int congestionDistance = Math.abs(stakeMark - previousStakeMark); |
|
|
|
if (congestionDistance > StakeMarkConstant.MAX_INTERVAL_MILLIMETER_WAVE_RADAR) { |
|
|
|
totalCongestionDistance.addAndGet(defaultCongestionDistance); |
|
|
|
defaultCongestionDistance = 0; |
|
|
|
} else { |
|
|
|
totalCongestionDistance.addAndGet(congestionDistance); |
|
|
|
// 如果当前路段被计算过,则累加拥堵路段数量
|
|
|
@ -458,6 +456,10 @@ public class TrafficAnalysis { |
|
|
|
previousAverageSpeed = averageSpeed; |
|
|
|
} |
|
|
|
|
|
|
|
if (defaultCongestionDistance != 0) { |
|
|
|
totalCongestionDistance.addAndGet(defaultCongestionDistance); |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
// 计算并返回路网整体的拥堵指数
|
|
|
@ -470,8 +472,6 @@ public class TrafficAnalysis { |
|
|
|
return metricsData; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 计算路段交通量 |
|
|
|
* |
|
|
@ -638,4 +638,127 @@ public class TrafficAnalysis { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 计算拥堵路段数据。 |
|
|
|
* |
|
|
|
* @param trafficSectionDataList 交通路段数据列表,包含各个路段的平均速度、交通量和行驶方向等信息。 |
|
|
|
* @return 拥堵路段数据列表,详细记录了每个拥堵路段的起始桩号、结束桩号、平均速度和行驶方向等信息。 |
|
|
|
*/ |
|
|
|
public List<DcCongestedSectionData> calculateCongestedSection(List<DcTrafficSectionData> trafficSectionDataList) { |
|
|
|
|
|
|
|
if (trafficSectionDataList == null || trafficSectionDataList.isEmpty()) { |
|
|
|
return Collections.emptyList(); |
|
|
|
} |
|
|
|
|
|
|
|
// 根据行驶方向对交通数据进行分组
|
|
|
|
Map<Byte, List<DcTrafficSectionData>> groupedByDirection = trafficSectionDataList.stream() |
|
|
|
.collect(Collectors.groupingBy(DcTrafficSectionData::getDirection)); |
|
|
|
|
|
|
|
List<DcCongestedSectionData> dcCongestedSectionDataList = new ArrayList<>(); |
|
|
|
|
|
|
|
groupedByDirection.forEach((directionData, trafficSectionList) -> { |
|
|
|
|
|
|
|
List<DcTrafficSectionData> sortedList; |
|
|
|
|
|
|
|
// 根据行驶方向,对交通路段数据进行排序,上行方向逆序,下行方向正序
|
|
|
|
if (directionData.equals(LaneDirectionEnum.UPWARD.getValue())) { |
|
|
|
sortedList = trafficSectionList.stream() |
|
|
|
.sorted(Comparator.comparing(DcTrafficSectionData::getStakeMark).reversed()) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
} else { |
|
|
|
sortedList = trafficSectionList.stream() |
|
|
|
.sorted(Comparator.comparing(DcTrafficSectionData::getStakeMark)) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
} |
|
|
|
|
|
|
|
int previousStakeMark = 0; |
|
|
|
int previousAverageSpeed = 0; |
|
|
|
int defaultCongestionDistance = 0; |
|
|
|
int trafficVolume = 0; |
|
|
|
ChannelCongestionLevelEnum previousCongestionLevel = null; |
|
|
|
DcCongestedSectionData congestedSectionData = null; |
|
|
|
|
|
|
|
// 遍历排序后的路段数据,计算每个路段的拥堵里程,并累加到总拥堵里程中
|
|
|
|
for (DcTrafficSectionData dcTrafficSectionData : sortedList) { |
|
|
|
|
|
|
|
int averageSpeed = dcTrafficSectionData.getAverageSpeed(); |
|
|
|
int stakeMark = dcTrafficSectionData.getStakeMark(); |
|
|
|
trafficVolume = dcTrafficSectionData.getTrafficVolume(); |
|
|
|
|
|
|
|
boolean isCongestion = ChannelCongestionLevelEnum.isCongestion(averageSpeed, trafficVolume); |
|
|
|
|
|
|
|
// 判断当前路段是否拥堵,如果不是拥堵路段且前一个路段是拥堵的,则更新拥堵里程并创建新的拥堵路段数据
|
|
|
|
if (!isCongestion && previousAverageSpeed != 0) { |
|
|
|
int congestionDistance = Math.abs(stakeMark - previousStakeMark); |
|
|
|
if (congestionDistance > defaultCongestionDistance) { |
|
|
|
if (directionData.equals(LaneDirectionEnum.UPWARD.getValue())) { |
|
|
|
previousStakeMark -= defaultCongestionDistance; |
|
|
|
} else { |
|
|
|
previousStakeMark += defaultCongestionDistance; |
|
|
|
} |
|
|
|
congestedSectionData.setEndStakeMark(previousStakeMark); |
|
|
|
} else { |
|
|
|
previousStakeMark = stakeMark; |
|
|
|
congestedSectionData.setEndStakeMark(stakeMark); |
|
|
|
} |
|
|
|
|
|
|
|
congestedSectionData.setEndStakeMark(previousStakeMark); |
|
|
|
previousCongestionLevel = ChannelCongestionLevelEnum.fromSpeed(averageSpeed, trafficVolume); |
|
|
|
previousAverageSpeed = 0; |
|
|
|
defaultCongestionDistance = 0; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (!isCongestion) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// 处理同等级别拥堵的路段,计算拥堵距离,更新拥堵路段的结束桩号
|
|
|
|
if (ChannelCongestionLevelEnum.isWithinLevel(averageSpeed, previousCongestionLevel)) { |
|
|
|
int congestionDistance = Math.abs(stakeMark - previousStakeMark); |
|
|
|
// 对于超出最大间隔的拥堵路段,更新拥堵里程
|
|
|
|
if (congestionDistance > StakeMarkConstant.MAX_INTERVAL_MILLIMETER_WAVE_RADAR) { |
|
|
|
if (directionData.equals(LaneDirectionEnum.UPWARD.getValue())) { |
|
|
|
previousStakeMark -= defaultCongestionDistance; |
|
|
|
} else { |
|
|
|
previousStakeMark += defaultCongestionDistance; |
|
|
|
} |
|
|
|
congestedSectionData.setEndStakeMark(previousStakeMark); |
|
|
|
} else { |
|
|
|
previousStakeMark = stakeMark; |
|
|
|
congestedSectionData.setEndStakeMark(stakeMark); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 如果当前路段拥堵级别改变,创建新的拥堵路段数据,并更新起始桩号和默认拥堵距离
|
|
|
|
congestedSectionData = new DcCongestedSectionData(); |
|
|
|
congestedSectionData.setAverageSpeed(averageSpeed); |
|
|
|
congestedSectionData.setDirection(directionData); |
|
|
|
congestedSectionData.setStartStakeMark(stakeMark); |
|
|
|
|
|
|
|
dcCongestedSectionDataList.add(congestedSectionData); |
|
|
|
|
|
|
|
previousStakeMark = stakeMark; |
|
|
|
defaultCongestionDistance = ChannelCongestionLevelEnum.fromSpeed(averageSpeed).getDefaultCongestionDistance(); |
|
|
|
} |
|
|
|
|
|
|
|
previousAverageSpeed = averageSpeed; |
|
|
|
previousCongestionLevel = ChannelCongestionLevelEnum.fromSpeed(averageSpeed); |
|
|
|
} |
|
|
|
|
|
|
|
// 处理遍历完所有路段后的拥堵状态,确保最后一个拥堵路段也被记录
|
|
|
|
boolean isCongestion = ChannelCongestionLevelEnum.isCongestion(previousAverageSpeed, trafficVolume); |
|
|
|
|
|
|
|
if (isCongestion && congestedSectionData != null) { |
|
|
|
// 根据行驶方向更新拥堵里程
|
|
|
|
if (directionData.equals(LaneDirectionEnum.UPWARD.getValue())) { |
|
|
|
previousStakeMark -= defaultCongestionDistance; |
|
|
|
} else { |
|
|
|
previousStakeMark += defaultCongestionDistance; |
|
|
|
} |
|
|
|
congestedSectionData.setEndStakeMark(previousStakeMark); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
return dcCongestedSectionDataList; |
|
|
|
} |
|
|
|
} |
|
|
|