Commit f369a95c authored by hanbing's avatar hanbing

[update] 新信号评价-方案评价-方案详情曲线图

parent 9aa6b062
package net.wanji.opt.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.List;
/**
* @author Kent HAN
* @date 2023/6/9 13:52
*/
@Data
@ApiModel(value = "CurveChartBO", description = "方案详情-曲线图")
public class CurveChartBO {
@ApiModelProperty(value = "路口ID")
private String crossId;
@ApiModelProperty(value = "时间粒度(分钟)", required = true)
private Integer minutes;
@ApiModelProperty(value = "年月日,格式 2023/7/9")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy/M/d", timezone = "GMT+8")
private Date problemDate;
@ApiModelProperty(value = "开始时间 HH:mm")
private String startTime;
@ApiModelProperty(value = "结束时间 HH:mm")
private String endTime;
@ApiModelProperty(value = "指标编号 1不停车通过率,2一/二/三次及以上停车通过率...")
private String MetricCode;
private List<DirTurn> dirTurnList;
@NoArgsConstructor
@Data
public static class DirTurn {
@ApiModelProperty(value = "进口方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北")
private String dir;
@ApiModelProperty(value = "转向:u掉头;l左转;s直行;r右转")
private String turn;
}
}
......@@ -25,6 +25,6 @@ public class MetricsDetailBO {
@ApiModelProperty(value = "日期 yyyy-MM-dd", required = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date date;
@ApiModelProperty(value = "对比时间间隔(分钟)", required = true)
@ApiModelProperty(value = "时间粒度(分钟)", required = true)
private Integer minutes;
}
......@@ -7,6 +7,7 @@ import io.swagger.annotations.ApiResponses;
import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.databus.bo.CrossIdBO;
import net.wanji.opt.bo.CrossSchemeListBO;
import net.wanji.opt.bo.CurveChartBO;
import net.wanji.opt.bo.ProblemSchemeBO;
import net.wanji.opt.bo.SchemeDetailOverallBO;
import net.wanji.opt.service.impl.SchemeEvaluateServiceImpl;
......@@ -97,4 +98,17 @@ public class SchemeEvaluateController {
return JsonViewObject.newInstance().success(res);
}
@ApiOperation(value = "方案详情-曲线图", notes = "方案详情-曲线图", response = JsonViewObject.class,
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@PostMapping(value = "/curveChart",
produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
@ApiResponses({
@ApiResponse(code = 200, message = "OK", response = SchemeEvaluateCurveChartVO.class),
})
public JsonViewObject curveChart(@RequestBody CurveChartBO curveChartBO)
throws ParseException, NoSuchFieldException, IllegalAccessException {
List<SchemeEvaluateCurveChartVO> res = schemeEvaluateService.curveChart(curveChartBO);
return JsonViewObject.newInstance().success(res);
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package net.wanji.opt.service;
import net.wanji.databus.bo.CrossIdBO;
import net.wanji.opt.bo.CrossSchemeListBO;
import net.wanji.opt.bo.CurveChartBO;
import net.wanji.opt.bo.ProblemSchemeBO;
import net.wanji.opt.bo.SchemeDetailOverallBO;
import net.wanji.opt.vo.*;
......@@ -19,4 +20,6 @@ public interface SchemeEvaluateService {
SchemeEvaluateSchemeDetailOverallVO schemeDetailOverall(SchemeDetailOverallBO schemeDetailOverallBO) throws ParseException;
SchemeEvaluateSchemeDetailedProblemVO detailedProblem(SchemeDetailOverallBO schemeDetailOverallBO) throws ParseException;
List<SchemeEvaluateCurveChartVO> curveChart(CurveChartBO curveChartBO) throws ParseException, NoSuchFieldException, IllegalAccessException;
}
......@@ -304,8 +304,8 @@ public class RunningEvaluateServiceImpl implements RunningEvaluateService {
// 按时间段分组
Map<String, List<MetricHistDTO>> groupedByTime = metricHistDTOList.stream()
.collect(Collectors.groupingBy(metricHistDTO -> {
long timestampInSeconds = metricHistDTO.getBatchTime() * 1000L;
Date date = new Date(timestampInSeconds);
long timestampInMillSeconds = metricHistDTO.getBatchTime() * 1000L;
Date date = new Date(timestampInMillSeconds);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
int minuteOfDay = date.getMinutes() + date.getHours() * 60;
int roundedMinute = (minuteOfDay / minutes) * minutes;
......
......@@ -9,6 +9,7 @@ import net.wanji.common.enums.CrossInOutEnum;
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.CrossIdBO;
import net.wanji.databus.dao.entity.BaseCrossSchedulesPO;
import net.wanji.databus.dao.entity.BaseCrossSchedulesPlanPO;
......@@ -17,6 +18,8 @@ import net.wanji.databus.dao.entity.CrossSectionPO;
import net.wanji.databus.dao.mapper.*;
import net.wanji.databus.po.*;
import net.wanji.opt.bo.CrossSchemeListBO;
import net.wanji.opt.bo.CurveChartBO;
import net.wanji.opt.bo.CurveChartBO.DirTurn;
import net.wanji.opt.bo.ProblemSchemeBO;
import net.wanji.opt.bo.SchemeDetailOverallBO;
import net.wanji.opt.dao.mapper.strategy.SceneMapper;
......@@ -31,6 +34,7 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
......@@ -160,8 +164,13 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
for (StrategyAndMetricsEnum.Metrics metric : entry.getValue()) {
SchemeEvaluateStrategyMetricMenuVO.EvaluateMetric evaluateMetric =
new SchemeEvaluateStrategyMetricMenuVO.EvaluateMetric();
evaluateMetric.setMetricCode(metric.getCode());
String metricCode = metric.getCode();
evaluateMetric.setMetricCode(metricCode);
evaluateMetric.setMetricName(metric.getDescription());
if (Objects.equals(metricCode, StrategyAndMetricsEnum.Metrics.LOAD_BALANCE.getCode())
|| Objects.equals(metricCode, StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getCode())) {
evaluateMetric.setIsShownInDetail(0);
}
metricInfoList.add(evaluateMetric);
}
return metricInfoList;
......@@ -311,6 +320,165 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
return vo;
}
@Override
public List<SchemeEvaluateCurveChartVO> curveChart(CurveChartBO curveChartBO)
throws ParseException, NoSuchFieldException, IllegalAccessException {
String crossId = curveChartBO.getCrossId();
Integer minutes = curveChartBO.getMinutes();
Date problemDate = curveChartBO.getProblemDate();
String startTime = curveChartBO.getStartTime();
String endTime = curveChartBO.getEndTime();
String dateStr = dateFormat.format(problemDate);
String concatenatedStartTime = dateStr + " " + startTime;
String concatenatedEndTime = dateStr + " " + endTime;
int startTimeStamp = (int) (timeFormat.parse(concatenatedStartTime).getTime() / 1000);
int endTimeStamp = (int) (timeFormat.parse(concatenatedEndTime).getTime() / 1000);
String metricCode = curveChartBO.getMetricCode();
List<DirTurn> dirTurnList = curveChartBO.getDirTurnList();
List<SchemeEvaluateCurveChartVO> res = new ArrayList<>();
List<String> minuteSectionArray = TimeArrayUtil.getMinuteSectionArray(minutes);
for (DirTurn dirTurn : dirTurnList) {
String turnType = dirTurn.getTurn();
String dirCode = dirTurn.getDir();
int dirInt = Integer.parseInt(dirCode);
if (ObjectUtil.isEmpty(turnType)) {
// 查询该方向所有的车道ID
List<String> laneIds = baseCrossDirInfoMapper.selectLaneIds(crossId, dirInt);
// 查询该方向,该时段内全量数据
List<CrossDirDataHistPOExt> crossDirDataHistPOList = crossDirDataHistMapper.selectByMetrics(
crossId, dirInt, startTimeStamp, endTimeStamp, laneIds);
// 按时间段分组
Map<String, List<CrossDirDataHistPOExt>> groupedByTime = crossDirDataHistPOList.stream()
.collect(Collectors.groupingBy(po -> {
long timestampInMillSeconds = po.getBatchTime() * 1000L;
Date date = new Date(timestampInMillSeconds);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
int minuteOfDay = date.getMinutes() + date.getHours() * 60;
int roundedMinute = (minuteOfDay / minutes) * minutes;
date.setHours(roundedMinute / 60);
date.setMinutes(roundedMinute % 60);
return sdf.format(date);
}));
// 按照时间粒度聚合
for (String section : minuteSectionArray) {
SchemeEvaluateCurveChartVO vo = new SchemeEvaluateCurveChartVO();
vo.setMetricTime(section);
vo.setDir(dirCode);
vo.setTurn(turnType);
List<CrossDirDataHistPOExt> poList = groupedByTime.get(section);
String metricField = StrategyAndMetricsEnum.Metrics.getFieldByCode(metricCode);
Field declaredField = CrossDirDataHistPOExt.class.getField(metricField);
declaredField.setAccessible(true);
if (CollectionUtil.isNotEmpty(poList)) {
int metricSum = 0;
for (CrossDirDataHistPOExt crossDirDataHistPOExt : poList) {
Integer intValue = getDirInteger(crossDirDataHistPOExt, declaredField);
metricSum += intValue;
}
int size = poList.size();
vo.setMetricValue(metricSum / size);
}
res.add(vo);
}
} else {
// 查询该转向所有的车道ID
Integer intTurnCode = BaseEnum.TurnTypeEnum.getIntCodeByStrCode(turnType);
List<String> laneIds = baseCrossTurnInfoMapper.selectLaneIds(crossId, dirInt, intTurnCode);
// 查询该方向,该转向,该时段内全量数据
List<CrossTurnDataHistPOExt> crossTurnDataHistPOList = crossTurnDataHistMapper.selectByMetrics(
crossId, dirInt, turnType, startTimeStamp, endTimeStamp, laneIds);
// 按时间段分组
Map<String, List<CrossTurnDataHistPOExt>> groupedByTime = crossTurnDataHistPOList.stream()
.collect(Collectors.groupingBy(po -> {
long timestampInMillSeconds = po.getBatchTime() * 1000L;
Date date = new Date(timestampInMillSeconds);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
int minuteOfDay = date.getMinutes() + date.getHours() * 60;
int roundedMinute = (minuteOfDay / minutes) * minutes;
date.setHours(roundedMinute / 60);
date.setMinutes(roundedMinute % 60);
return sdf.format(date);
}));
// 按照时间粒度聚合
for (String section : minuteSectionArray) {
SchemeEvaluateCurveChartVO vo = new SchemeEvaluateCurveChartVO();
vo.setMetricTime(section);
vo.setDir(dirCode);
vo.setTurn(turnType);
List<CrossTurnDataHistPOExt> poList = groupedByTime.get(section);
String metricField = StrategyAndMetricsEnum.Metrics.getFieldByCode(metricCode);
Field declaredField = CrossTurnDataHistPOExt.class.getField(metricField);
declaredField.setAccessible(true);
if (CollectionUtil.isNotEmpty(poList)) {
int metricSum = 0;
for (CrossTurnDataHistPOExt crossTurnDataHistPOExt : poList) {
Integer intValue = getTurnInteger(crossTurnDataHistPOExt, declaredField);
metricSum += intValue;
}
int size = poList.size();
vo.setMetricValue(metricSum / size);
}
res.add(vo);
}
}
}
return res;
}
private static final Set<String> SPECIAL_METRICS = new HashSet<>();
static {
SPECIAL_METRICS.add(StrategyAndMetricsEnum.Metrics.NO_STOP_RATE.getField());
SPECIAL_METRICS.add(StrategyAndMetricsEnum.Metrics.STOP_RATE.getField());
SPECIAL_METRICS.add(StrategyAndMetricsEnum.Metrics.GREEN_LIGHT_EFFICIENCY.getField());
SPECIAL_METRICS.add(StrategyAndMetricsEnum.Metrics.EFFUSION_RATE.getField());
SPECIAL_METRICS.add(StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getField());
}
private Integer getIntegerFromObject(Object object, Field declaredField) throws IllegalAccessException {
Object objValue = declaredField.get(object);
String fieldName = declaredField.getName();
if (SPECIAL_METRICS.contains(fieldName) && objValue instanceof Double) {
objValue = (int) Math.round((Double) objValue * 100);
}
if (objValue instanceof Integer) {
return (Integer) objValue;
} else if (objValue instanceof Double) {
return (int) Math.round((Double) objValue);
} else {
throw new IllegalArgumentException("字段值不是 int 或 double");
}
}
@NotNull
private Integer getTurnInteger(CrossTurnDataHistPOExt crossTurnDataHistPO, Field declaredField)
throws IllegalAccessException {
return getIntegerFromObject(crossTurnDataHistPO, declaredField);
}
@NotNull
private Integer getDirInteger(CrossDirDataHistPOExt crossDirDataHistPO, Field declaredField)
throws IllegalAccessException {
return getIntegerFromObject(crossDirDataHistPO, declaredField);
}
private void buildSecurityDetailVO(List<CrossDirDataHistPO> crossDirDataHistPOList,
List<CrossTurnDataHistPO> crossTurnDataHistPOList,
SchemeEvaluateSchemeDetailedProblemVO vo, String crossId,
......@@ -325,6 +493,7 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
SchemeEvaluateSchemeDetailedProblemVO.TableContent tableContent =
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(BaseEnum.SignalDirectionEnum.getNameByCode(dirCode) + "进口");
tableContent.setPositionCode(dirCode.toString());
// 流量加总
int flow = crossDirDataHistPOList.stream()
......@@ -342,15 +511,6 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.EFFUSION_RATE.getCode(),
effusionRateMax * 100 + StrategyAndMetricsEnum.Metrics.EFFUSION_RATE.getUnit());
// 绿灯间隔清空率取最大
double clearRateMax = crossDirDataHistPOList.stream()
.filter(item -> Objects.equals(item.getDirType(), dirCode)
&& Objects.equals(item.getInOutType(), CrossInOutEnum.IN.getCode()))
.mapToDouble(CrossDirDataHistPO::getClearRate)
.max()
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getCode(),
clearRateMax + StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getUnit());
// 方向级别三急一速数量
// 查询该方向所有的车道ID
List<String> laneIds = baseCrossDirInfoMapper.selectLaneIds(crossId, dirCode);
......@@ -364,7 +524,7 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
List<CrossTurnDataHistPO> dirTurnPOList = crossTurnDataHistPOList.stream()
.filter(item -> Objects.equals(item.getInDir(), dirCode))
.collect(Collectors.toList());
tableContent.setSubList(buildSecuritySublist(problemList, dirTurnPOList, dirCode, crossId,
tableContent.setSubList(buildSecuritySublist(dirTurnPOList, dirCode, crossId,
startTimeStamp, endTimeStamp));
tableContent.setMetricsMap(metricsMap);
......@@ -378,16 +538,27 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
}
vo.setTableContentList(tableContentList);
if (CollectionUtil.isNotEmpty(problemList)) {
problemList.add("其他方向满足安全保障需求");
// 计算指标是否合格
List<CrossDataHistPO> crossDataHistPOList = crossDataHistMapper.selectByCrossIdAndStartEnd(
crossId, startTimeStamp, endTimeStamp);
Double maxCrossSaturation = crossDataHistMapper.selectMaxSaturation(crossId, startTimeStamp, endTimeStamp);
// 绿灯间隔清空率取最大
OptionalDouble clearRateMax = crossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getClearRate)
.max();
boolean isQualified = calcSecurity(maxCrossSaturation, clearRateMax);
if (!isQualified) {
problemList.add("路口存在安全隐患");
} else {
problemList.add("路口满足安全保障需求");
}
vo.setProblems(problemList);
}
private List<SchemeEvaluateSchemeDetailedProblemVO.TableContent> buildSecuritySublist(
List<String> problemList, List<CrossTurnDataHistPO> currentDirTurnPOList,
Integer dirCode, String crossId, int startTimeStamp, int endTimeStamp) {
List<CrossTurnDataHistPO> currentDirTurnPOList, Integer dirCode, String crossId,
int startTimeStamp, int endTimeStamp) {
List<SchemeEvaluateSchemeDetailedProblemVO.TableContent> tableContentList = new ArrayList<>();
// 获取该方向的每个转向
List<String> turnTypes = currentDirTurnPOList.stream()
......@@ -400,6 +571,7 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(TurnConvertEnum.getDescByCode(turnType));
tableContent.setPositionCode(turnType);
Map<String, String> metricsMap = new HashMap<>();
// 流量加总
......@@ -416,14 +588,6 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.EFFUSION_RATE.getCode(),
effusionRateMax * 100 + StrategyAndMetricsEnum.Metrics.EFFUSION_RATE.getUnit());
// 绿灯间隔清空率取最大
double clearRateMax = currentDirTurnPOList.stream()
.filter(item -> Objects.equals(item.getTurnType(), turnType))
.mapToDouble(CrossTurnDataHistPO::getClearRate)
.max()
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getCode(),
clearRateMax + StrategyAndMetricsEnum.Metrics.CLEAR_RATE.getUnit());
// 转向级别三急一速数量
// 查询该转向所有的车道ID
Integer intTurnCode = BaseEnum.TurnTypeEnum.getIntCodeByStrCode(turnType);
......@@ -434,20 +598,6 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
metricsMap.put(StrategyAndMetricsEnum.Metrics.EMERGENCY_COUNT.getCode(),
emergencyCount + StrategyAndMetricsEnum.Metrics.EMERGENCY_COUNT.getUnit());
// 饱和度取最大
double maxSaturation = currentDirTurnPOList.stream()
.filter(item -> Objects.equals(item.getTurnType(), turnType))
.mapToDouble(CrossTurnDataHistPO::getSturation)
.max()
.orElse(0);
// 计算指标是否合格
boolean isQualified = calcSecurity(maxSaturation, OptionalDouble.of(clearRateMax));
if (!isQualified) {
tableContent.setHasProblem(1);
problemList.add(BaseEnum.SignalDirectionEnum.getNameByCode(dirCode) + "进口"
+ TurnConvertEnum.getDescByCode(turnType) + "存在安全隐患");
}
tableContent.setMetricsMap(metricsMap);
tableContentList.add(tableContent);
......@@ -468,6 +618,7 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
SchemeEvaluateSchemeDetailedProblemVO.TableContent tableContent =
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(BaseEnum.SignalDirectionEnum.getNameByCode(dirCode) + "进口");
tableContent.setPositionCode(dirCode.toString());
// 流量加总
int flow = crossDirDataHistPOList.stream()
......@@ -495,15 +646,6 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.SATURATION.getCode(),
maxSaturation + StrategyAndMetricsEnum.Metrics.SATURATION.getUnit());
// 负载均衡度取最大
double maxLoadBalance = crossDirDataHistPOList.stream()
.filter(item -> Objects.equals(item.getDirType(), dirCode)
&& Objects.equals(item.getInOutType(), CrossInOutEnum.IN.getCode()))
.mapToDouble(CrossDirDataHistPO::getLoadBalance)
.max()
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.LOAD_BALANCE.getCode(),
maxLoadBalance + StrategyAndMetricsEnum.Metrics.LOAD_BALANCE.getUnit());
// 筛选当前方向的转向数据
List<CrossTurnDataHistPO> dirTurnPOList = crossTurnDataHistPOList.stream()
......@@ -542,6 +684,8 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(TurnConvertEnum.getDescByCode(turnType));
tableContent.setPositionCode(turnType);
Map<String, String> metricsMap = new HashMap<>();
// 流量加总
......@@ -567,14 +711,6 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
.orElse(0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.SATURATION.getCode(),
maxSaturation + StrategyAndMetricsEnum.Metrics.SATURATION.getUnit());
// 负载均衡度取最大
double maxLoadBalance = currentDirTurnPOList.stream()
.filter(item -> Objects.equals(item.getTurnType(), turnType))
.mapToDouble(CrossTurnDataHistPO::getLoadBalance)
.max()
.orElse(0.0);
metricsMap.put(StrategyAndMetricsEnum.Metrics.LOAD_BALANCE.getCode(),
maxLoadBalance + StrategyAndMetricsEnum.Metrics.LOAD_BALANCE.getUnit());
// 计算指标是否合格
boolean isQualified = calcBalance(maxSaturation, greenLightEfficiencyMax);
......@@ -605,6 +741,7 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
SchemeEvaluateSchemeDetailedProblemVO.TableContent tableContent =
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(BaseEnum.SignalDirectionEnum.getNameByCode(dirCode) + "进口");
tableContent.setPositionCode(dirCode.toString());
// 流量加总
int flow = crossDirDataHistPOList.stream()
......@@ -692,6 +829,8 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
vo.setTableContentList(tableContentList);
if (CollectionUtil.isNotEmpty(problemList)) {
problemList.add("其他方向运行效率良好");
} else {
problemList.add("各方向运行效率良好");
}
vo.setProblems(problemList);
}
......@@ -710,6 +849,8 @@ public class SchemeEvaluateServiceImpl implements SchemeEvaluateService {
new SchemeEvaluateSchemeDetailedProblemVO.TableContent();
tableContent.setPosition(TurnConvertEnum.getDescByCode(turnType));
tableContent.setPositionCode(turnType);
Map<String, String> metricsMap = new HashMap<>();
// 流量加总
......
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 = "SchemeEvaluateCurveChartVO", description = "方案详情-曲线图")
public class SchemeEvaluateCurveChartVO {
@ApiModelProperty(value = "进口方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北")
private String dir;
@ApiModelProperty(value = "转向:u掉头;l左转;s直行;r右转")
private String turn;
@ApiModelProperty(value = "时间")
private String metricTime;
@ApiModelProperty(value = "指标数值")
private Integer metricValue;
}
......@@ -27,6 +27,9 @@ public class SchemeEvaluateSchemeDetailedProblemVO {
@NoArgsConstructor
@Data
public static class TableContent {
@ApiModelProperty(value = "位置代码 1,2,3...表示进口方向;l,r,s,u表示转向")
private String positionCode;
@ApiModelProperty(value = "位置")
private String position;
......
......@@ -33,5 +33,8 @@ public class SchemeEvaluateStrategyMetricMenuVO {
@ApiModelProperty(value = "指标名称")
private String metricName;
@ApiModelProperty(value = "在方案详情页是否展示,0否 1是")
private Integer isShownInDetail = 1;
}
}
......@@ -32,30 +32,40 @@ public class StrategyAndMetricsEnum {
@Getter
public enum Metrics {
NO_STOP_RATE("1", "不停车通过率", "%"),
STOP_RATE("2", "一/二/三次及以上停车通过率", "%"),
AVERAGE_DELAY("3", "平均延误", "s"),
MAX_QUEUE_LENGTH("4", "最大排队长度", "m"),
STOP_TIMES("5", "停车次数", "次"),
AVERAGE_SPEED("6", "平均速度", "km/h"),
GREEN_LIGHT_EFFICIENCY("7", "绿灯有效利用率", "%"),
SATURATION("8", "饱和度", ""),
LOAD_BALANCE("9", "负载均衡度", ""),
EFFUSION_RATE("10", "溢流率", "%"),
CLEAR_RATE("11", "绿灯间隔清空率", "%"),
EMERGENCY_COUNT("12", "三急一速数量", "");
NO_STOP_RATE("1", "不停车通过率", "%", "noStopRate"),
STOP_RATE("2", "一/二/三次及以上停车通过率", "%", "oneStopRate"),
AVERAGE_DELAY("3", "平均延误", "s", "delayTime"),
MAX_QUEUE_LENGTH("4", "最大排队长度", "m", "queueLength"),
STOP_TIMES("5", "停车次数", "次", "stopTimes"),
AVERAGE_SPEED("6", "平均速度", "km/h", "speed"),
GREEN_LIGHT_EFFICIENCY("7", "绿灯有效利用率", "%", "greenLightEfficiency"),
SATURATION("8", "饱和度", "", "sturation"),
LOAD_BALANCE("9", "负载均衡度", "", "loadBalance"),
EFFUSION_RATE("10", "溢流率", "%", "effusionRate"),
CLEAR_RATE("11", "绿灯间隔清空率", "%", "clearRate"),
EMERGENCY_COUNT("12", "三急一速数量", "", "emergencyCount");
private final String code;
private final String description;
private final String unit;
private final String field; // 实体类中的字段名
Metrics(String code, String description, String unit) {
Metrics(String code, String description, String unit, String field) {
this.code = code;
this.description = description;
this.unit = unit;
this.field = field;
}
public static String getFieldByCode(String code) {
for (Metrics value : Metrics.values()) {
if (value.code.equals(code)) {
return value.field;
}
}
return null;
}
}
public static final Map<Strategy, List<Metrics>> STRATEGY_METRICS_MAP;
......
......@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.wanji.databus.bo.CrossDirDataHistAvgBO;
import net.wanji.databus.dto.MetricHistDTO;
import net.wanji.databus.po.CrossDirDataHistPO;
import net.wanji.databus.po.CrossDirDataHistPOExt;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
......@@ -44,4 +45,7 @@ public interface CrossDirDataHistMapper extends BaseMapper<CrossDirDataHistPO> {
Double selectMaxSaturation(String crossId, Integer dirType, Integer inOutType, int startStamp, int endStamp);
Double selectMaxGreenLightEfficiency(String crossId, Integer dirCode, Integer code, int startTimeStamp, int endTimeStamp);
List<CrossDirDataHistPOExt> selectByMetrics(String crossId, int dirInt, int startTimeStamp, int endTimeStamp, List<String> laneIds);
}
......@@ -3,6 +3,7 @@ package net.wanji.databus.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.wanji.databus.dto.MetricHistDTO;
import net.wanji.databus.po.CrossTurnDataHistPO;
import net.wanji.databus.po.CrossTurnDataHistPOExt;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
......@@ -23,4 +24,6 @@ public interface CrossTurnDataHistMapper extends BaseMapper<CrossTurnDataHistPO>
List<CrossTurnDataHistPO> selectByCrossId(String crossId, long endTimeStamp, long startTimeStamp);
List<MetricHistDTO> selectMetricHistDTO(String crossId, int startStamp, int endStamp);
List<CrossTurnDataHistPOExt> selectByMetrics(String crossId, int dirInt, String turnType, int startTimeStamp, int endTimeStamp, List<String> laneIds);
}
package net.wanji.databus.po;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author duanruiming
* @date 2023/03/12 20:49
*/
@Data
public class CrossDataHistPOExt extends CrossDataRealtimePO {
@ApiModelProperty(value = "三急一速数量", notes = "")
private Integer emergencyCount;
}
package net.wanji.databus.po;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author duanruiming
* @date 2023/03/12 20:51
*/
@Data
public class CrossDirDataHistPOExt extends CrossDirDataRealtimePO {
@ApiModelProperty(value = "三急一速数量", notes = "")
public Integer emergencyCount;
}
......@@ -16,60 +16,60 @@ import java.util.Date;
@ApiModel(value = "CrossDirDataRealtimePO", description = "路口转向实时数据")
public class CrossDirDataRealtimePO {
@ApiModelProperty(name = "路口方向ID(路口ID_方向_进出口_主辅路序号)",notes = "")
private String id;
public String id;
@ApiModelProperty(name = "路口方向类型:1北;2东北;3东;4东南;5南;6西南;7西;8西北",notes = "")
private Integer dirType;
public Integer dirType;
@ApiModelProperty(name = "进出口类型:1进口;2出口",notes = "")
private Integer inOutType;
public Integer inOutType;
@ApiModelProperty(name = "路口编号",notes = "")
private String crossId;
public String crossId;
@ApiModelProperty(name = "路段长度",notes = "")
private Double length;
public Double length;
@ApiModelProperty(name = "交通状态:1畅通;2缓行;3拥堵;4严重拥堵;5未知",notes = "")
private Integer status;
public Integer status;
@ApiModelProperty(name = "交通指数",notes = "")
private Double trafficIndex;
public Double trafficIndex;
@ApiModelProperty(name = "开始时间",notes = "")
private Date startTime;
public Date startTime;
@ApiModelProperty(name = "通行能力",notes = "")
private Integer capacity;
public Integer capacity;
@ApiModelProperty(name = "持续时间",notes = "")
private Integer duration;
public Integer duration;
@ApiModelProperty(name = "交通流量(辆)",notes = "")
private Integer flow;
public Integer flow;
@ApiModelProperty(name = "平均速度(km/h)",notes = "")
private Double speed;
public Double speed;
@ApiModelProperty(name = "排队长(米)",notes = "")
private Double queueLength;
public Double queueLength;
@ApiModelProperty(name = "停车次数",notes = "")
private Double stopTimes;
public Double stopTimes;
@ApiModelProperty(name = "延误时间",notes = "")
private Integer delayTime;
public Integer delayTime;
@ApiModelProperty(name = "饱和度",notes = "")
private Double sturation;
public Double sturation;
@ApiModelProperty(name = "不停车率",notes = "")
private Double noStopRate;
public Double noStopRate;
@ApiModelProperty(name = "一次停车率",notes = "")
private Double oneStopRate;
public Double oneStopRate;
@ApiModelProperty(name = "二次停车率",notes = "")
private Double twoStopRate;
public Double twoStopRate;
@ApiModelProperty(name = "三次停车率",notes = "")
private Double threeStopRate;
public Double threeStopRate;
@ApiModelProperty(name = "采集时间(10位时间戳)",notes = "")
private Integer batchTime;
public Integer batchTime;
@ApiModelProperty(name = "创建时间",notes = "")
private Date gmtCreate ;
public Date gmtCreate ;
@ApiModelProperty(name = "修改时间",notes = "")
private Date gmtModified ;
public Date gmtModified ;
@ApiModelProperty(name = "溢流率:交叉口间路段车辆排队长度超出可容纳空间的时长与观测总时长的百分比",notes = "")
private Double effusionRate;
public Double effusionRate;
@ApiModelProperty(value = "绿灯间隔清空率", notes = "")
private Double clearRate;
public Double clearRate;
@ApiModelProperty(value = "负载均衡度", notes = "")
private Double loadBalance;
public Double loadBalance;
@ApiModelProperty(value = "绿灯有效利用率", notes = "")
private Double greenLightEfficiency;
public Double greenLightEfficiency;
}
package net.wanji.databus.po;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author duanruiming
* @date 2023/03/12 20:54
*/
@Data
public class CrossTurnDataHistPOExt extends CrossTurnDataRealtimePO {
@ApiModelProperty(value = "三急一速数量", notes = "")
public Integer emergencyCount;
}
......@@ -18,83 +18,83 @@ import java.util.Date;
public class CrossTurnDataRealtimePO {
/** 转向ID(路口ID_驶入方向_转向类型) */
@ApiModelProperty(name = "转向ID(路口ID_驶入方向_转向类型)",notes = "")
private String id ;
public String id ;
/** 转向类型:u掉头;l左转;s直行;r右转; */
@ApiModelProperty(name = "转向类型:u掉头;l左转;s直行;r右转;",notes = "")
private String turnType ;
public String turnType ;
/** 驶入方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北 */
@ApiModelProperty(name = "驶入方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北",notes = "")
private Integer inDir ;
public Integer inDir ;
/** 驶出方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北 */
@ApiModelProperty(name = "驶出方向:1北;2东北;3东;4东南;5南;6西南;7西;8西北",notes = "")
private Integer outDir ;
public Integer outDir ;
/** 路口ID */
@ApiModelProperty(name = "路口ID",notes = "")
private String crossId ;
public String crossId ;
/** 交通流量(辆) */
@ApiModelProperty(name = "交通流量(辆)",notes = "")
private Integer flow ;
public Integer flow ;
@ApiModelProperty(name = "交通状态:1畅通;2缓行;3拥堵;4严重拥堵;5未知",notes = "")
private Integer status;
public Integer status;
@ApiModelProperty(name = "交通指数",notes = "")
private Double trafficIndex;
public Double trafficIndex;
/** 平均速度(km/h) */
@ApiModelProperty(name = "平均速度(km/h)",notes = "")
private Double speed ;
public Double speed ;
/** 驶入速度(km/h) */
@ApiModelProperty(name = "驶入速度(km/h)",notes = "")
private Double inSpeed ;
public Double inSpeed ;
/** 驶出速度(km/h) */
@ApiModelProperty(name = "驶出速度(km/h)",notes = "")
private Double outSpeed ;
public Double outSpeed ;
/** 排队长度(米) */
@ApiModelProperty(name = "排队长度(米)",notes = "")
private Double queueLength ;
public Double queueLength ;
/** 停车次数(次) */
@ApiModelProperty(name = "停车次数(次)",notes = "")
private Double stopTimes ;
public Double stopTimes ;
/** 延误时间(秒) */
@ApiModelProperty(name = "延误时间(秒)",notes = "")
private Integer delayTime ;
public Integer delayTime ;
/** 饱和度 */
@ApiModelProperty(name = "饱和度",notes = "")
private Double sturation ;
public Double sturation ;
/** 车头间距(米) */
@ApiModelProperty(name = "车头间距(米)",notes = "")
private Double vehheadDist ;
public Double vehheadDist ;
/** 车头时距(秒) */
@ApiModelProperty(name = "车头时距(秒)",notes = "")
private Double vehheadTime ;
public Double vehheadTime ;
/** 可信度:0~1 */
@ApiModelProperty(name = "可信度:0~1",notes = "")
private Double quality ;
public Double quality ;
@ApiModelProperty(name = "不停车率",notes = "")
private Double noStopRate;
public Double noStopRate;
@ApiModelProperty(name = "一次停车率",notes = "")
private Double oneStopRate;
public Double oneStopRate;
@ApiModelProperty(name = "二次停车率",notes = "")
private Double twoStopRate;
public Double twoStopRate;
@ApiModelProperty(name = "三次停车率",notes = "")
private Double threeStopRate;
public Double threeStopRate;
@ApiModelProperty(name = "开始时间",notes = "")
private Date startTime;
public Date startTime;
/** 采集时间(10位时间戳) */
@ApiModelProperty(name = "采集时间(10位时间戳)",notes = "")
private Integer batchTime ;
public Integer batchTime ;
/** 创建时间 */
@ApiModelProperty(name = "创建时间",notes = "")
private Date gmtCreate ;
public Date gmtCreate ;
/** 修改时间 */
@ApiModelProperty(name = "修改时间",notes = "")
private Date gmtModified ;
public Date gmtModified ;
@ApiModelProperty(value = "绿灯间隔清空率", notes = "")
private Double clearRate;
public Double clearRate;
@ApiModelProperty(value = "负载均衡度", notes = "")
private Double loadBalance;
public Double loadBalance;
@ApiModelProperty(value = "绿灯有效利用率", notes = "")
private Double greenLightEfficiency;
public Double greenLightEfficiency;
@ApiModelProperty(name = "溢流率:交叉口间路段车辆排队长度超出可容纳空间的时长与观测总时长的百分比",notes = "")
private Double effusionRate;
public Double effusionRate;
}
......@@ -161,4 +161,34 @@
and batch_time <![CDATA[ <= ]]> #{endStamp}
</select>
<select id="selectByMetrics" resultType="net.wanji.databus.po.CrossDirDataHistPOExt">
SELECT <include refid="Base_Column_List"/>,
<choose>
<when test="laneIds != null and laneIds.size() > 0">
(
SELECT COUNT(*)
FROM holo_roadnet_jinan.t_event_info
WHERE type IN ('33', '34', '35', '6')
AND UNIX_TIMESTAMP(start_time) <![CDATA[ >= ]]> #{startTimeStamp}
AND UNIX_TIMESTAMP(start_time) <![CDATA[ <= ]]> #{endTimeStamp}
AND cross_id = #{crossId}
AND lane_id IN
<foreach collection="laneIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
)
</when>
<otherwise>
0
</otherwise>
</choose>
AS emergencyCount
FROM t_cross_dir_data_hist
WHERE cross_id = #{crossId}
AND in_out_type = 1
AND dir_type != #{dirInt}
AND batch_time <![CDATA[ <= ]]> #{endTimeStamp}
AND batch_time <![CDATA[ >= ]]> #{startTimeStamp}
</select>
</mapper>
\ No newline at end of file
......@@ -87,4 +87,35 @@
order by batch_time
</select>
<select id="selectByMetrics" resultType="net.wanji.databus.po.CrossTurnDataHistPOExt">
SELECT <include refid="Base_Column_List"/>,
<choose>
<when test="laneIds != null and laneIds.size() > 0">
(
SELECT COUNT(*)
FROM holo_roadnet_jinan.t_event_info
WHERE type IN ('33', '34', '35', '6')
AND UNIX_TIMESTAMP(start_time) <![CDATA[ >= ]]> #{startTimeStamp}
AND UNIX_TIMESTAMP(start_time) <![CDATA[ <= ]]> #{endTimeStamp}
AND cross_id = #{crossId}
AND lane_id IN
<foreach collection="laneIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
)
</when>
<otherwise>
0
</otherwise>
</choose>
AS emergencyCount
FROM t_cross_turn_data_hist
WHERE cross_id = #{crossId}
AND turn_type = #{turnType}
AND in_dir != #{dirInt}
AND batch_time <![CDATA[ <= ]]> #{endTimeStamp}
AND batch_time <![CDATA[ >= ]]> #{startTimeStamp}
</select>
</mapper>
\ No newline at end of file
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