Commit 86267df5 authored by hanbing's avatar hanbing

[update] 城市大脑-干线评价-干线运行分析

parent 4087d0ae
......@@ -7,6 +7,7 @@ import io.swagger.annotations.ApiResponses;
import net.wanji.common.annotation.aspect.AspectLog;
import net.wanji.common.enums.BaseEnum;
import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.databus.bo.GreenwaveStartEndDateBO;
import net.wanji.opt.bo.*;
import net.wanji.opt.service.impl.MainlineEvaluateServiceImpl;
import net.wanji.opt.vo.*;
......@@ -93,4 +94,16 @@ public class MainlineEvaluateController {
List<MainlineCrossEvaluateVO> res = mainlineEvaluateService.mainlineCrossEvaluate(bo);
return JsonViewObject.newInstance().success(res);
}
@ApiOperation(value = "干线运行分析", notes = "干线运行分析", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/mainlineRunningAnalyse",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = MainlineRunningAnalyseVO.class),
})
public JsonViewObject mainlineRunningAnalyse(@RequestBody GreenwaveStartEndDateBO bo) {
List<MainlineRunningAnalyseVO> res = mainlineEvaluateService.mainlineRunningAnalyse(bo);
return JsonViewObject.newInstance().success(res);
}
}
\ No newline at end of file
package net.wanji.opt.service;
import net.wanji.databus.bo.GreenwaveStartEndDateBO;
import net.wanji.opt.bo.*;
import net.wanji.opt.vo.*;
......@@ -18,4 +19,6 @@ public interface MainlineEvaluateService {
MainlineSchemeEvaluateVO mainlineSchemeEvaluate(MainlineSchemeEvaluateBO bo);
List<MainlineCrossEvaluateVO> mainlineCrossEvaluate(MainlineCrossEvaluateBO bo);
List<MainlineRunningAnalyseVO> mainlineRunningAnalyse(GreenwaveStartEndDateBO bo);
}
package net.wanji.opt.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.enums.BaseEnum;
......@@ -9,6 +10,7 @@ import net.wanji.common.enums.StrategyAndMetricsEnum;
import net.wanji.common.enums.TurnConvertEnum;
import net.wanji.common.utils.tool.CrossUtil;
import net.wanji.common.utils.tool.TimeArrayUtil;
import net.wanji.databus.bo.GreenwaveStartEndDateBO;
import net.wanji.databus.dao.entity.*;
import net.wanji.databus.dao.mapper.*;
import net.wanji.databus.po.*;
......@@ -1025,6 +1027,152 @@ public class MainlineEvaluateServiceImpl implements MainlineEvaluateService {
return res;
}
@Override
public List<MainlineRunningAnalyseVO> mainlineRunningAnalyse(GreenwaveStartEndDateBO bo) {
Integer greenwaveId = bo.getId();
Date startDate = bo.getStartDate();
Date endDate = bo.getEndDate();
if (isZeros(endDate)) {
endDate = DateUtil.offsetDay(endDate, 1); // 包含最后一天
}
long startTime = startDate.getTime();
long endTime = endDate.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String boStartTimeStr = sdf.format(startDate);
String boEndTimeStr = sdf.format(endDate);
List<GreenwaveHistPO> greenwaveHistPOList =
greenwaveHistMapper.selectByIdAndTimeSection(greenwaveId, boStartTimeStr, boEndTimeStr);
// 找出拥堵时段
List<MainlineRunningAnalyseVO> congestionList = new ArrayList<>();
for (GreenwaveHistPO po : greenwaveHistPOList) {
if (po.getStatus() == 3) {
MainlineRunningAnalyseVO vo = new MainlineRunningAnalyseVO();
vo.setStartTime(po.getStartTime());
vo.setEndTime(po.getGmtModified());
congestionList.add(vo);
}
}
// 找出溢出时段
List<GreenwaveCrossPO> greenwaveCrossPOList = greenwaveCrossMapper.selectByGreenwaveId(greenwaveId);
// 找出绿波包含的路口
Map<String, GreenwaveCrossPO> uniqueMap = greenwaveCrossPOList.stream()
.collect(Collectors.toMap(
GreenwaveCrossPO::getCrossId, // 使用crossId作为键
Function.identity(), // 使用对象本身作为值
(existing, replacement) -> existing)); // 如果有重复的key, 保留第一个
List<GreenwaveCrossPO> uniqueList = new ArrayList<>(uniqueMap.values());
// 路口ID对应的路口历史数据
Map<String, List<CrossDataHistPO>> crossIdDataMap = new HashMap<>();
for (GreenwaveCrossPO greenwaveCrossPO : uniqueList) {
String crossId = greenwaveCrossPO.getCrossId();
List<CrossDataHistPO> crossDataHistPOList = crossDataHistMapper.selectByCrossIdAndStartEnd(
crossId, (int) (startTime / 1000), (int) (endTime / 1000));
crossIdDataMap.put(crossId, crossDataHistPOList);
}
List<MainlineRunningAnalyseVO> spilloverList = crossIdDataMap.values().stream()
.flatMap(List::stream)
.filter(hist -> hist.getStatus() == 3)
.map(hist -> new MainlineRunningAnalyseVO(2, hist.getStartTime(), hist.getEndTime()))
.collect(Collectors.toList());
// 合并交叉时段
List<MainlineRunningAnalyseVO> finalSpilloverList = mergeIntervals(spilloverList);
// 用溢出覆盖拥堵
List<MainlineRunningAnalyseVO> congestionSpilloverList = mergeAndAdjustLists(congestionList, finalSpilloverList);
SimpleDateFormat sdf2 = new SimpleDateFormat("H:mm");
Iterator<MainlineRunningAnalyseVO> iterator = congestionSpilloverList.iterator();
while (iterator.hasNext()) {
MainlineRunningAnalyseVO item = iterator.next();
if (item.getStartTime().equals(item.getEndTime())) {
iterator.remove();
} else {
long durationInSeconds = (item.getEndTime().getTime() - item.getStartTime().getTime()) / 1000;
String timeSpan = sdf2.format(item.getStartTime()) + "-" + sdf2.format(item.getEndTime());
item.setDuration((int) durationInSeconds);
item.setTimeSpan(timeSpan);
}
}
return congestionSpilloverList;
}
private List<MainlineRunningAnalyseVO> mergeAndAdjustLists(List<MainlineRunningAnalyseVO> congestionList,
List<MainlineRunningAnalyseVO> finalSpilloverList) {
List<MainlineRunningAnalyseVO> congestionSpilloverList = new ArrayList<>();
for (MainlineRunningAnalyseVO item : congestionList) {
MainlineRunningAnalyseVO newItem = new MainlineRunningAnalyseVO(3, item.getStartTime(), item.getEndTime());
congestionSpilloverList.add(newItem);
}
for (MainlineRunningAnalyseVO spilloverItem : finalSpilloverList) {
for (MainlineRunningAnalyseVO congestionItem : congestionSpilloverList) {
if (congestionItem.getStatus() == 3 && overlaps(congestionItem, spilloverItem)) {
// 以溢出时段为准修改拥堵时段
adjustTimes(congestionItem, spilloverItem);
}
}
congestionSpilloverList.add(new MainlineRunningAnalyseVO(
2, spilloverItem.getStartTime(), spilloverItem.getEndTime()));
}
return congestionSpilloverList;
}
private void adjustTimes(MainlineRunningAnalyseVO congestionItem, MainlineRunningAnalyseVO spilloverItem) {
if (congestionItem.getStartTime().before(spilloverItem.getStartTime())) {
congestionItem.setEndTime(spilloverItem.getStartTime());
} else if (congestionItem.getEndTime().after(spilloverItem.getEndTime())) {
congestionItem.setStartTime(spilloverItem.getEndTime());
} else {
congestionItem.setEndTime(congestionItem.getStartTime()); // 待删除
}
}
private boolean overlaps(MainlineRunningAnalyseVO congestionItem, MainlineRunningAnalyseVO spilloverItem) {
return congestionItem.getEndTime().after(spilloverItem.getStartTime())
&& congestionItem.getStartTime().before(spilloverItem.getEndTime());
}
private List<MainlineRunningAnalyseVO> mergeIntervals(List<MainlineRunningAnalyseVO> intervals) {
if (intervals.size() <= 1) {
return intervals;
}
// 按开始时间排序
intervals.sort(Comparator.comparing(MainlineRunningAnalyseVO::getStartTime));
List<MainlineRunningAnalyseVO> result = new ArrayList<>();
MainlineRunningAnalyseVO current = intervals.get(0);
for (MainlineRunningAnalyseVO interval : intervals) {
if (interval.getStartTime().before(current.getEndTime()) || interval.getStartTime().equals(current.getEndTime())) {
// 合并交叉时段
current.setEndTime(new Date(Math.max(current.getEndTime().getTime(), interval.getEndTime().getTime())));
} else {
// 未出现交叉
result.add(current);
current = interval;
}
}
result.add(current);
return result;
}
private boolean isZeros(Date endDate) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(endDate);
return calendar.get(Calendar.HOUR_OF_DAY) == 0 &&
calendar.get(Calendar.MINUTE) == 0 &&
calendar.get(Calendar.SECOND) == 0 &&
calendar.get(Calendar.MILLISECOND) == 0;
}
private void fillNonCoordValue(MainlineCrossEvaluateVO mainlineCrossEvaluateVO, List<Integer> coordDirCodeList,
String crossId, List<CrossDirDataHistPOExt> crossDirDataHistPOList,
List<BaseCrossDirInfoPO> baseCrossDirInfoPOList) {
......
package net.wanji.opt.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author Kent HAN
* @date 2023/2/9 8:38
*/
@Data
@NoArgsConstructor
@ApiModel(value = "MainlineRunningAnalyseVO", description = "干线运行分析")
public class MainlineRunningAnalyseVO {
@ApiModelProperty(value = "交通状态:1畅通;2溢出;3拥堵")
private Integer status;
@ApiModelProperty(value = "时段")
private String timeSpan;
@ApiModelProperty(value = "时长(秒)")
private Integer duration;
@ApiModelProperty(value = "开始时间")
private Date startTime;
@ApiModelProperty(value = "结束时间")
private Date endTime;
public MainlineRunningAnalyseVO(Integer status, Date startTime, Date endTime) {
this.status = status;
this.startTime = startTime;
this.endTime = endTime;
}
}
package net.wanji.databus.bo;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class GreenwaveStartEndDateBO {
@ApiModelProperty(value = "绿波ID")
private Integer id ;
@ApiModelProperty(value = "开始日期 yyyy-MM-dd HH:mm:ss 或者 yyyy-MM-dd")
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date startDate;
@ApiModelProperty(value = "结束日期 yyyy-MM-dd HH:mm:ss 或者 yyyy-MM-dd")
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date endDate;
}
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