Commit 60e346f0 authored by hanbing's avatar hanbing

[update] 场景评价--增加失衡、溢出处理方式

parent 7a79347f
...@@ -6,14 +6,12 @@ import io.swagger.annotations.ApiResponse; ...@@ -6,14 +6,12 @@ import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses; import io.swagger.annotations.ApiResponses;
import net.wanji.common.framework.rest.JsonViewObject; import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.databus.bo.CrossIdAndStartEndDateBO; import net.wanji.databus.bo.CrossIdAndStartEndDateBO;
import net.wanji.databus.bo.HeatMapBO;
import net.wanji.opt.bo.AbnormalDetailBO; import net.wanji.opt.bo.AbnormalDetailBO;
import net.wanji.opt.bo.MetricsTurnAndLaneBO; import net.wanji.opt.bo.MetricsTurnAndLaneBO;
import net.wanji.opt.bo.SceneMetricsDetailBO; import net.wanji.opt.bo.SceneMetricsDetailBO;
import net.wanji.opt.service.impl.SceneEvaluateServiceImpl; import net.wanji.opt.service.impl.SceneEvaluateServiceImpl;
import net.wanji.opt.vo.SceneEvaluateAbnormalDetailVO; import net.wanji.opt.vo.*;
import net.wanji.opt.vo.SceneEvaluateAbnormalDistributeVO;
import net.wanji.opt.vo.SceneEvaluateMetricsLaneVO;
import net.wanji.opt.vo.SceneEvaluateMetricsTurnVO;
import net.wanji.opt.vo.SceneMetricsDetailVO; import net.wanji.opt.vo.SceneMetricsDetailVO;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
...@@ -101,4 +99,16 @@ public class SceneEvaluateController { ...@@ -101,4 +99,16 @@ public class SceneEvaluateController {
SceneEvaluateMetricsLaneVO res = sceneEvaluateService.metricsLane(bo); SceneEvaluateMetricsLaneVO res = sceneEvaluateService.metricsLane(bo);
return JsonViewObject.newInstance().success(res); return JsonViewObject.newInstance().success(res);
} }
@ApiOperation(value = "场景评价热力图", notes = "场景评价热力图", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/heatMap",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = SceneEvaluateHeatMapVO.class),
})
public JsonViewObject heatMap(@RequestBody HeatMapBO bo) {
List<SceneEvaluateHeatMapVO> res = sceneEvaluateService.heatMap(bo);
return JsonViewObject.newInstance().success(res);
}
} }
\ No newline at end of file
package net.wanji.opt.service; package net.wanji.opt.service;
import net.wanji.databus.bo.CrossIdAndStartEndDateBO; import net.wanji.databus.bo.CrossIdAndStartEndDateBO;
import net.wanji.databus.bo.HeatMapBO;
import net.wanji.opt.bo.AbnormalDetailBO; import net.wanji.opt.bo.AbnormalDetailBO;
import net.wanji.opt.bo.MetricsTurnAndLaneBO; import net.wanji.opt.bo.MetricsTurnAndLaneBO;
import net.wanji.opt.bo.SceneMetricsDetailBO; import net.wanji.opt.bo.SceneMetricsDetailBO;
import net.wanji.opt.vo.SceneEvaluateAbnormalDetailVO; import net.wanji.opt.vo.*;
import net.wanji.opt.vo.SceneEvaluateAbnormalDistributeVO;
import net.wanji.opt.vo.SceneEvaluateMetricsLaneVO;
import net.wanji.opt.vo.SceneEvaluateMetricsTurnVO;
import net.wanji.opt.vo.SceneMetricsDetailVO; import net.wanji.opt.vo.SceneMetricsDetailVO;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
...@@ -25,4 +23,6 @@ public interface SceneEvaluateService { ...@@ -25,4 +23,6 @@ public interface SceneEvaluateService {
SceneEvaluateMetricsTurnVO metricsTurn(MetricsTurnAndLaneBO bo) throws ParseException; SceneEvaluateMetricsTurnVO metricsTurn(MetricsTurnAndLaneBO bo) throws ParseException;
SceneEvaluateMetricsLaneVO metricsLane(MetricsTurnAndLaneBO bo) throws ParseException; SceneEvaluateMetricsLaneVO metricsLane(MetricsTurnAndLaneBO bo) throws ParseException;
List<SceneEvaluateHeatMapVO> heatMap(HeatMapBO bo);
} }
...@@ -9,6 +9,7 @@ import net.wanji.common.enums.StrategyAndMetricsEnum; ...@@ -9,6 +9,7 @@ import net.wanji.common.enums.StrategyAndMetricsEnum;
import net.wanji.common.utils.tool.CrossUtil; import net.wanji.common.utils.tool.CrossUtil;
import net.wanji.common.utils.tool.TimeArrayUtil; import net.wanji.common.utils.tool.TimeArrayUtil;
import net.wanji.databus.bo.CrossIdAndStartEndDateBO; import net.wanji.databus.bo.CrossIdAndStartEndDateBO;
import net.wanji.databus.bo.HeatMapBO;
import net.wanji.databus.dao.entity.BaseCrossSchemePO; import net.wanji.databus.dao.entity.BaseCrossSchemePO;
import net.wanji.databus.dao.entity.CrossSectionPO; import net.wanji.databus.dao.entity.CrossSectionPO;
import net.wanji.databus.dao.mapper.*; import net.wanji.databus.dao.mapper.*;
...@@ -29,6 +30,7 @@ import java.lang.reflect.Method; ...@@ -29,6 +30,7 @@ import java.lang.reflect.Method;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -193,7 +195,7 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService { ...@@ -193,7 +195,7 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService {
vo.setStartTime(startTime); vo.setStartTime(startTime);
vo.setTimeline(getTimeline(startTime, newEndTime)); vo.setTimeline(getTimeline(startTime, newEndTime));
// todo 暂时只有拥堵,后期扩展考虑增加字段 // 只有拥堵显示
if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) { if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) {
Integer delayTime = calcCrossDelayTime(sceneCrossDataHistPOList); Integer delayTime = calcCrossDelayTime(sceneCrossDataHistPOList);
Integer level = calcCongestionLevel(delayTime); Integer level = calcCongestionLevel(delayTime);
...@@ -204,6 +206,12 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService { ...@@ -204,6 +206,12 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService {
if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) { if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) {
String congestionDirs = crossDataHistPO.getCongestionDirs(); String congestionDirs = crossDataHistPO.getCongestionDirs();
vo.setDirs(buildDirs(congestionDirs)); vo.setDirs(buildDirs(congestionDirs));
} else if (Objects.equals(status, CrossStatusEnum.UNBALANCE.getCode())) {
String unbalanceDirs = crossDataHistPO.getUnbalanceDirs();
vo.setDirs(buildDirs(unbalanceDirs));
} else if (Objects.equals(status, CrossStatusEnum.SPILLOVER.getCode())) {
String spilloverDirs = crossDataHistPO.getSpilloverDirs();
vo.setDirs(buildDirs(spilloverDirs));
} }
// 查找当前路口全部方案 // 查找当前路口全部方案
...@@ -394,6 +402,88 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService { ...@@ -394,6 +402,88 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService {
return res; return res;
} }
@Override
public List<SceneEvaluateHeatMapVO> heatMap(HeatMapBO bo) {
String crossId = bo.getCrossId();
Date startDate = bo.getStartDate();
Date endDate = bo.getEndDate();
endDate = DateUtil.offsetDay(endDate, 1); // 包含最后一天
int startStamp = (int) (startDate.getTime() / 1000); // 10位时间戳
int endStamp = (int) (endDate.getTime() / 1000);
Integer status = bo.getStatus();
List<SceneEvaluateHeatMapVO> res = new ArrayList<>();
List<CrossDataHistPO> crossDataHistPOList = crossDataHistMapper.selectByCrossIdAndStartEnd(
crossId, startStamp, endStamp);
// 根据 status 值选择分组字段
Function<CrossDataHistPO, String> groupByField;
switch (status) {
case 1:
groupByField = CrossDataHistPO::getUnbalanceDirs;
break;
case 2:
groupByField = CrossDataHistPO::getCongestionDirs;
break;
case 3:
groupByField = CrossDataHistPO::getSpilloverDirs;
break;
default:
throw new IllegalArgumentException("状态值非法");
}
// 过滤 status 字段值为 status 变量的对象,并按照方向分组
Map<String, List<CrossDataHistPO>> grouped = crossDataHistPOList.stream()
.flatMap(po -> {
String dirs = "";
if (status == 1) {
dirs = po.getUnbalanceDirs();
} else if (status == 2) {
dirs = po.getCongestionDirs();
} else if (status == 3) {
dirs = po.getSpilloverDirs();
}
return Arrays.stream(dirs.split(","))
.map(dir -> new AbstractMap.SimpleEntry<>(dir, po));
})
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue, Collectors.toList())
));
// 对每个组进行处理,仅保留 start_time 相同的记录中 duration 最大的一条
Map<String, List<CrossDataHistPO>> filteredGrouped = grouped.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream()
.collect(Collectors.groupingBy(CrossDataHistPO::getStartTime))
.values().stream()
.map(list -> list.stream().max(Comparator.comparingInt(CrossDataHistPO::getDuration))
.orElse(null))
.collect(Collectors.toList())
));
// 遍历 filteredGrouped,提取每个 key 和与该 key 关联的列表的元素个数
filteredGrouped.forEach((key, list) -> {
SceneEvaluateHeatMapVO sceneEvaluateHeatMapVO = new SceneEvaluateHeatMapVO();
if (ObjectUtil.isNotEmpty(key)) {
sceneEvaluateHeatMapVO.setDir(Integer.parseInt(key));
if (!status.equals(CrossStatusEnum.CONGESTION.getCode())) {
if (list.isEmpty()) {
sceneEvaluateHeatMapVO.setIsUnbalanceOrSpillOver(0);
} else {
sceneEvaluateHeatMapVO.setIsUnbalanceOrSpillOver(1);
}
} else {
Integer delayTime = calcCrossDelayTime(list);
Integer level = calcCongestionLevel(delayTime);
sceneEvaluateHeatMapVO.setLevel(level);
}
sceneEvaluateHeatMapVO.setStatus(status);
res.add(sceneEvaluateHeatMapVO);
}
});
return res;
}
private SceneEvaluateMetricsLaneVO.LaneListElement buildLaneListElement( private SceneEvaluateMetricsLaneVO.LaneListElement buildLaneListElement(
Map.Entry<Integer, List<CrossLaneDataHistPOExt>> entry, Integer status) { Map.Entry<Integer, List<CrossLaneDataHistPOExt>> entry, Integer status) {
SceneEvaluateMetricsLaneVO.LaneListElement element = new SceneEvaluateMetricsLaneVO.LaneListElement(); SceneEvaluateMetricsLaneVO.LaneListElement element = new SceneEvaluateMetricsLaneVO.LaneListElement();
......
...@@ -24,7 +24,7 @@ public class SceneEvaluateAbnormalDetailVO { ...@@ -24,7 +24,7 @@ public class SceneEvaluateAbnormalDetailVO {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
private Date startTime ; private Date startTime ;
// todo 目前只有拥堵,后期扩展考虑增加字段 // 只有拥堵显示
@ApiModelProperty(value = "等级",notes = "0畅通 1轻度 2中度 3严重") @ApiModelProperty(value = "等级",notes = "0畅通 1轻度 2中度 3严重")
private Integer level ; private Integer level ;
......
package net.wanji.opt.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Kent HAN
* @date 2023/2/9 8:38
*/
@Data
@NoArgsConstructor
@ApiModel(value = "SceneEvaluateHeatMapVO", description = "场景评价热力图")
public class SceneEvaluateHeatMapVO {
@ApiModelProperty(value = "方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北")
private Integer dir;
@ApiModelProperty(value = "等级,只有拥堵显示 0畅通 1轻度 2中度 3严重")
private Integer level ;
@ApiModelProperty(value = "是否失衡或溢出,只有失衡或溢出显示 0否 1是")
private Integer isUnbalanceOrSpillOver ;
@ApiModelProperty(value = "路口状态 0正常 1 失衡 2 拥堵 3 溢出")
private Integer status;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment