Commit bb66610a authored by hanbing's avatar hanbing

[add] 新信号评价-运行评价-异常事件详情

parent 952a14b3
package net.wanji.web.controller;
import net.wanji.web.service.impl.CrossManageServiceImpl;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* @author hanbing
* @date 2023/01/04 16:10
*/
@RequestMapping("/control")
@RestController
public class FeignController {
private final CrossManageServiceImpl crossManageServiceImpl;
public FeignController(CrossManageServiceImpl crossManageServiceImpl) {
this.crossManageServiceImpl = crossManageServiceImpl;
}
@PostMapping("/findPlanId")
public Integer findPlanId(Date datetime, String dateStr, String crossId) {
Integer planId = crossManageServiceImpl.findPlanId(datetime, dateStr, crossId);
return planId;
}
}
...@@ -508,7 +508,7 @@ public class CrossManageServiceImpl implements CrossManageService { ...@@ -508,7 +508,7 @@ public class CrossManageServiceImpl implements CrossManageService {
return timeInt; return timeInt;
} }
private Integer findPlanId(Date datetime, String dateStr, String crossId) { public Integer findPlanId(Date datetime, String dateStr, String crossId) {
CrossIdBO crossIdBO = new CrossIdBO(); CrossIdBO crossIdBO = new CrossIdBO();
crossIdBO.setCrossId(crossId); crossIdBO.setCrossId(crossId);
RunningPlanDTO runningPlanDTO = runningPlanServiceImpl.listRunningPlan(crossIdBO); RunningPlanDTO runningPlanDTO = runningPlanServiceImpl.listRunningPlan(crossIdBO);
......
package net.wanji.feign.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author duanruiming
* @date 2023/01/09 15:23
*/
@Configuration(value = "FeignControlClientsConfig")
@EnableFeignClients(basePackages = "net.wanji.feign")
@Slf4j
public class FeignControlClientsConfig {
@Value("${control.url}")
private String url;
@Bean
public void testUrl() {
log.info("===========feign config url control:" + url);
}
}
package net.wanji.feign.service;
import net.wanji.feign.config.FeignControlClientsConfig;
import net.wanji.feign.service.common.FeignCommon;
import org.springframework.cloud.openfeign.FeignClient;
/**
* @author duanruiming
* @date 2023/05/19 9:05
*/
@FeignClient(name = "ControlFeignClients", url = "${control.url}",
configuration = FeignControlClientsConfig.class)
public interface ControlFeignClients extends FeignCommon {
}
package net.wanji.feign.service; package net.wanji.feign.service;
import net.wanji.feign.config.FeignDTClientsConfig; import net.wanji.feign.config.FeignDTClientsConfig;
import net.wanji.feign.service.common.UtcFeignCommon; import net.wanji.feign.service.common.FeignCommon;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
/** /**
...@@ -9,5 +9,5 @@ import org.springframework.cloud.openfeign.FeignClient; ...@@ -9,5 +9,5 @@ import org.springframework.cloud.openfeign.FeignClient;
* @date 2023/05/19 9:05 * @date 2023/05/19 9:05
*/ */
@FeignClient(name = "UtcDTFeignClients", url = "${utc.dt.service.url}", configuration = FeignDTClientsConfig.class) @FeignClient(name = "UtcDTFeignClients", url = "${utc.dt.service.url}", configuration = FeignDTClientsConfig.class)
public interface UtcDTFeignClients extends UtcFeignCommon { public interface UtcDTFeignClients extends FeignCommon {
} }
package net.wanji.feign.service; package net.wanji.feign.service;
import net.wanji.feign.config.FeignClientsConfig; import net.wanji.feign.config.FeignClientsConfig;
import net.wanji.feign.service.common.UtcFeignCommon; import net.wanji.feign.service.common.FeignCommon;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
/** /**
...@@ -9,5 +9,5 @@ import org.springframework.cloud.openfeign.FeignClient; ...@@ -9,5 +9,5 @@ import org.springframework.cloud.openfeign.FeignClient;
* @date 2023/01/09 15:29 * @date 2023/01/09 15:29
*/ */
@FeignClient(name = "UtcFeignClients", url = "${utc.service.url}", configuration = FeignClientsConfig.class) @FeignClient(name = "UtcFeignClients", url = "${utc.service.url}", configuration = FeignClientsConfig.class)
public interface UtcFeignClients extends UtcFeignCommon { public interface UtcFeignClients extends FeignCommon {
} }
package net.wanji.feign.service; package net.wanji.feign.service;
import net.wanji.feign.config.FeignHisenseClientsConfig; import net.wanji.feign.config.FeignHisenseClientsConfig;
import net.wanji.feign.service.common.UtcFeignCommon; import net.wanji.feign.service.common.FeignCommon;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
/** /**
...@@ -10,5 +10,5 @@ import org.springframework.cloud.openfeign.FeignClient; ...@@ -10,5 +10,5 @@ import org.springframework.cloud.openfeign.FeignClient;
*/ */
@FeignClient(name = "UtcHisenseFeignClients", url = "${utc.hisense.service.url}", @FeignClient(name = "UtcHisenseFeignClients", url = "${utc.hisense.service.url}",
configuration = FeignHisenseClientsConfig.class) configuration = FeignHisenseClientsConfig.class)
public interface UtcHisenseFeignClients extends UtcFeignCommon { public interface UtcHisenseFeignClients extends FeignCommon {
} }
...@@ -15,7 +15,7 @@ import java.util.Date; ...@@ -15,7 +15,7 @@ import java.util.Date;
* @author duanruiming * @author duanruiming
* @date 2023/05/19 15:48 * @date 2023/05/19 15:48
*/ */
public interface UtcFeignCommon { public interface FeignCommon {
/** /**
* 信号机状态 * 信号机状态
...@@ -108,4 +108,7 @@ public interface UtcFeignCommon { ...@@ -108,4 +108,7 @@ public interface UtcFeignCommon {
// 临时方案 // 临时方案
@PostMapping("/tempScheme") @PostMapping("/tempScheme")
JsonViewObject tempScheme(@RequestParam String crossCode, @RequestParam Integer schemeNo); JsonViewObject tempScheme(@RequestParam String crossCode, @RequestParam Integer schemeNo);
@PostMapping("/control/findPlanId")
Integer findPlanId(@RequestParam Date datetime, @RequestParam String dateStr, @RequestParam String crossId);
} }
utc.service.url=http://10.102.1.182:32000/utc utc.service.url=http://10.102.1.182:32000/utc
utc.dt.service.url=http://10.102.1.182:39002/utc-dt utc.dt.service.url=http://10.102.1.182:39002/utc-dt
utc.hisense.service.url=http://10.102.1.182:39003/utc-hisense utc.hisense.service.url=http://10.102.1.182:39003/utc-hisense
control.url=http://10.102.1.182:32001/web
utc.service.url=http://10.102.1.182:32000/utc utc.service.url=http://10.102.1.182:32000/utc
utc.dt.service.url=http://10.102.1.182:39002/utc-dt utc.dt.service.url=http://10.102.1.182:39002/utc-dt
utc.hisense.service.url=http://10.102.1.182:39003/utc-hisense utc.hisense.service.url=http://10.102.1.182:39003/utc-hisense
control.url=http://localhost:32001/web
utc.service.url=http://172.17.0.1:32000/utc utc.service.url=http://172.17.0.1:32000/utc
utc.dt.service.url=http://172.17.0.1:39002/utc-dt utc.dt.service.url=http://172.17.0.1:39002/utc-dt
utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense
control.url=http://172.17.0.1:32001/web
utc.service.url=http://172.17.0.1:32000/utc utc.service.url=http://172.17.0.1:32000/utc
utc.dt.service.url=http://172.17.0.1:39002/utc-dt utc.dt.service.url=http://172.17.0.1:39002/utc-dt
utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense
control.url=http://172.17.0.1:32001/web
utc.service.url=http://localhost:32000/utc utc.service.url=http://localhost:32000/utc
utc.dt.service.url=http://localhost:39002/utc-dt utc.dt.service.url=http://localhost:39002/utc-dt
utc.hisense.service.url=http://localhost:39003/utc-hisense utc.hisense.service.url=http://localhost:39003/utc-hisense
control.url=http://localhost:32001/web
utc.service.url=http://localhost:32000/utc utc.service.url=http://localhost:32000/utc
utc.dt.service.url=http://localhost:39002/utc-dt utc.dt.service.url=http://localhost:39002/utc-dt
utc.hisense.service.url=http://localhost:39003/utc-hisense utc.hisense.service.url=http://localhost:39003/utc-hisense
control.url=http://localhost:32001/web
utc.service.url=http://172.17.0.1:32000/utc utc.service.url=http://172.17.0.1:32000/utc
utc.dt.service.url=http://172.17.0.1:39002/utc-dt utc.dt.service.url=http://172.17.0.1:39002/utc-dt
utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense
control.url=http://172.17.0.1:32001/web
utc.service.url=http://172.17.0.1:32000/utc utc.service.url=http://172.17.0.1:32000/utc
utc.dt.service.url=http://172.17.0.1:39002/utc-dt utc.dt.service.url=http://172.17.0.1:39002/utc-dt
utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense utc.hisense.service.url=http://172.17.0.1:39003/utc-hisense
control.url=http://172.17.0.1:32001/web
...@@ -3,17 +3,25 @@ package net.wanji.opt.service.impl; ...@@ -3,17 +3,25 @@ package net.wanji.opt.service.impl;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.wanji.common.enums.CrossStatusEnum; import net.wanji.common.enums.CrossStatusEnum;
import net.wanji.common.enums.StrategyAndMetricsEnum;
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.dao.mapper.CrossDataHistMapper; import net.wanji.databus.dao.entity.BaseCrossSchemePO;
import net.wanji.databus.dao.entity.CrossSectionPO;
import net.wanji.databus.dao.mapper.*;
import net.wanji.databus.dto.MetricHistDTO; import net.wanji.databus.dto.MetricHistDTO;
import net.wanji.databus.po.CrossDataHistPO; import net.wanji.databus.po.CrossDataHistPO;
import net.wanji.databus.po.CrossDirDataHistPO;
import net.wanji.feign.service.ControlFeignClients;
import net.wanji.opt.bo.AbnormalDetailBO; import net.wanji.opt.bo.AbnormalDetailBO;
import net.wanji.opt.service.SceneEvaluateService; import net.wanji.opt.service.SceneEvaluateService;
import net.wanji.opt.vo.RunningEvaluateMetricsDetailVO; import net.wanji.opt.vo.RunningEvaluateMetricsDetailVO;
import net.wanji.opt.vo.SceneEvaluateAbnormalDetailVO; import net.wanji.opt.vo.SceneEvaluateAbnormalDetailVO;
import net.wanji.opt.vo.SceneEvaluateAbnormalDistributeVO; import net.wanji.opt.vo.SceneEvaluateAbnormalDistributeVO;
import net.wanji.opt.vo.SchemeEvaluateSchemeDetailOverallVO;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.text.ParseException; import java.text.ParseException;
...@@ -30,11 +38,23 @@ import java.util.stream.Collectors; ...@@ -30,11 +38,23 @@ import java.util.stream.Collectors;
public class SceneEvaluateServiceImpl implements SceneEvaluateService { public class SceneEvaluateServiceImpl implements SceneEvaluateService {
private final CrossDataHistMapper crossDataHistMapper; private final CrossDataHistMapper crossDataHistMapper;
private final RunningEvaluateServiceImpl runningEvaluateService; private final RunningEvaluateServiceImpl runningEvaluateService;
private final BaseCrossSchemeMapper baseCrossSchemeMapper;
private final BaseCrossSchedulesMapper baseCrossSchedulesMapper;
private final BaseCrossSchedulesPlanMapper baseCrossSchedulesPlanMapper;
private final ControlFeignClients controlFeignClients;
private final BaseCrossSectionMapper baseCrossSectionMapper;
private final CrossDirDataHistMapper crossDirDataHistMapper;
SimpleDateFormat HOUR_SDF = new SimpleDateFormat("HH:mm"); SimpleDateFormat HOUR_SDF = new SimpleDateFormat("HH:mm");
public SceneEvaluateServiceImpl(CrossDataHistMapper crossDataHistMapper, RunningEvaluateServiceImpl runningEvaluateService) { public SceneEvaluateServiceImpl(CrossDataHistMapper crossDataHistMapper, RunningEvaluateServiceImpl runningEvaluateService, @Qualifier("baseCrossSchemeMapper") BaseCrossSchemeMapper baseCrossSchemeMapper, @Qualifier("baseCrossSchedulesMapper") BaseCrossSchedulesMapper baseCrossSchedulesMapper, @Qualifier("baseCrossSchedulesPlanMapper") BaseCrossSchedulesPlanMapper baseCrossSchedulesPlanMapper, @Qualifier("net.wanji.feign.service.ControlFeignClients") ControlFeignClients controlFeignClients, @Qualifier("baseCrossSectionMapper") BaseCrossSectionMapper baseCrossSectionMapper, CrossDirDataHistMapper crossDirDataHistMapper) {
this.crossDataHistMapper = crossDataHistMapper; this.crossDataHistMapper = crossDataHistMapper;
this.runningEvaluateService = runningEvaluateService; this.runningEvaluateService = runningEvaluateService;
this.baseCrossSchemeMapper = baseCrossSchemeMapper;
this.baseCrossSchedulesMapper = baseCrossSchedulesMapper;
this.baseCrossSchedulesPlanMapper = baseCrossSchedulesPlanMapper;
this.controlFeignClients = controlFeignClients;
this.baseCrossSectionMapper = baseCrossSectionMapper;
this.crossDirDataHistMapper = crossDirDataHistMapper;
} }
@Override @Override
...@@ -149,9 +169,278 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService { ...@@ -149,9 +169,278 @@ public class SceneEvaluateServiceImpl implements SceneEvaluateService {
} }
} }
if (ObjectUtil.isEmpty(intersectingRecords)) {
throw new RuntimeException("该时段无异常事件");
}
CrossDataHistPO crossDataHistPO = intersectingRecords.get(0);
SceneEvaluateAbnormalDetailVO vo = new SceneEvaluateAbnormalDetailVO();
vo.setStatus(status);
Date startTime = crossDataHistPO.getStartTime();
Integer duration = crossDataHistPO.getDuration();
// 计算startTime加上duration后的时间
cal.setTime(startTime);
cal.add(Calendar.MINUTE, duration);
Date newEndTime = cal.getTime();
return null; List<CrossDataHistPO> sceneCrossDataHistPOList = getCrossDataHistPOList(startTime, newEndTime, crossId);
vo.setStartTime(startTime);
// todo 暂时只有拥堵,后期扩展考虑增加字段
if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) {
Integer delayTime = calcCrossDelayTime(sceneCrossDataHistPOList);
Integer level = calcCongestionLevel(delayTime);
vo.setLevel(level);
}
vo.setDuration(duration);
if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) {
String congestionDirs = crossDataHistPO.getCongestionDirs();
vo.setDirs(buildDirs(congestionDirs));
}
// 查找当前路口全部方案
List<BaseCrossSchemePO> baseCrossSchemePOList = baseCrossSchemeMapper.selectByCrossId(crossId);
// 找出当前计划
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String startDay = sdf.format(startTime);
Integer planId = controlFeignClients.findPlanId(startTime, startDay, crossId);
if (ObjectUtil.isEmpty(planId)) {
throw new RuntimeException("当前时段无正在运行的计划");
}
// 获取时段信息
List<CrossSectionPO> crossSectionPOList = baseCrossSectionMapper.selectByCrossAndPlan(crossId, planId);
// 根据 startTime 和 duration 查找相交的方案
// 将Date转换为"HH:mm"字符串
String newStartTimeStr = HOUR_SDF.format(startTime);
String newEndTimeStr = HOUR_SDF.format(newEndTime);
List<CrossSectionPO> intersectingSections = crossSectionPOList.stream()
.filter(po -> !(po.getEndTime().compareTo(newStartTimeStr) < 0
|| po.getStartTime().compareTo(newEndTimeStr) > 0))
.collect(Collectors.toList());
// 筛选baseCrossSchemePOList,找出id与intersectingSections中的schemeId相等的记录
List<BaseCrossSchemePO> matchedSchemes = baseCrossSchemePOList.stream()
.filter(baseScheme -> intersectingSections.stream()
.anyMatch(section -> section.getSchemeId().equals(baseScheme.getId())))
.collect(Collectors.toList());
vo.setPatternNames(buildPatternNames(matchedSchemes));
Double sturation = calcCrossSaturation(sceneCrossDataHistPOList);
String serviceLevel = CrossUtil.getServiceLevel(sturation);
vo.setServiceLevel(serviceLevel);
vo.setFlow(calcCrossFlow(sceneCrossDataHistPOList));
if (Objects.equals(status, CrossStatusEnum.CONGESTION.getCode())) {
vo.setOverallMetricsList(buildCrossCongestionMetrics(
crossId, startTime, newEndTime, sceneCrossDataHistPOList));
} else if (Objects.equals(status, CrossStatusEnum.UNBALANCE.getCode())) {
vo.setOverallMetricsList(buildCrossUnbalanceMetrics(crossId, startTime, newEndTime, sceneCrossDataHistPOList));
} else if (Objects.equals(status, CrossStatusEnum.SPILLOVER.getCode())) {
vo.setOverallMetricsList(buildCrossSpilloverMetrics(sceneCrossDataHistPOList));
}
return vo;
}
private List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> buildCrossSpilloverMetrics(
List<CrossDataHistPO> sceneCrossDataHistPOList) {
List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> res = new ArrayList<>();
// 最大排队长度
double maxQueueLength = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getQueueLength)
.max()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.MAX_QUEUE_LENGTH, maxQueueLength));
// 平均延误
double avgDelayTime = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getDelayTime)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.AVERAGE_DELAY, avgDelayTime));
// 平均停车次数
double avgStopTimes = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getStopTimes)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.STOP_TIMES, avgStopTimes));
// 溢流率
double avgEffusionRate = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getEffusionRate)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.EFFUSION_RATE, avgEffusionRate * 100));
return res;
}
private List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> buildCrossUnbalanceMetrics(
String crossId, Date startTime, Date newEndTime, List<CrossDataHistPO> sceneCrossDataHistPOList) {
List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> res = new ArrayList<>();
List<CrossDirDataHistPO> crossDirDataHistPOList = getCrossDirDataHistPOList(startTime, newEndTime, crossId);
// 用方向数据计算不停车通过率
double avgNoStopRate = crossDirDataHistPOList.stream()
.mapToDouble(CrossDirDataHistPO::getNoStopRate)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.NO_STOP_RATE, avgNoStopRate * 100));
// 用方向数据计算N次停车通过率
double maxOneStopRate = crossDirDataHistPOList.stream()
.mapToDouble(CrossDirDataHistPO::getOneStopRate)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.STOP_RATE, maxOneStopRate * 100));
// 空放次数-绿灯有效利用率小于80%
long emptyDischarges = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getGreenLightEfficiency)
.filter(efficiency -> efficiency < 0.8)
.count();
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.EMPTY_DISCHARGES, emptyDischarges));
// 绿灯有效利用率
double avgGreenLightEfficiency = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getGreenLightEfficiency)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.GREEN_LIGHT_EFFICIENCY,
avgGreenLightEfficiency * 100));
// 负载均衡度
double avgLoadBalance = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getLoadBalance)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.LOAD_BALANCE, avgLoadBalance));
return res;
}
private List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> buildCrossCongestionMetrics(
String crossId, Date startTime, Date newEndTime, List<CrossDataHistPO> sceneCrossDataHistPOList) {
List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> res = new ArrayList<>();
// 从方向数据计算N次停车通过率
List<CrossDirDataHistPO> crossDirDataHistPOList = getCrossDirDataHistPOList(startTime, newEndTime, crossId);
double maxOneStopRate = crossDirDataHistPOList.stream()
.mapToDouble(CrossDirDataHistPO::getOneStopRate)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.STOP_RATE, maxOneStopRate * 100));
double avgSpeed = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getSpeed)
.average()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.AVERAGE_SPEED, avgSpeed));
int maxDelayTime = sceneCrossDataHistPOList.stream()
.mapToInt(CrossDataHistPO::getDelayTime)
.max()
.orElse(0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.AVERAGE_DELAY, maxDelayTime));
double maxStopTimes = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getStopTimes)
.max()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.STOP_TIMES, maxStopTimes));
double maxQueueLength = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getQueueLength)
.max()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.MAX_QUEUE_LENGTH, maxQueueLength));
double maxEffusionRate = sceneCrossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getEffusionRate)
.max()
.orElse(0.0);
res.add(buildMetrics(StrategyAndMetricsEnum.Metrics.EFFUSION_RATE, maxEffusionRate * 100));
return res;
}
private SchemeEvaluateSchemeDetailOverallVO.OverallMetrics buildMetrics(
StrategyAndMetricsEnum.Metrics metricEnum, double value) {
int roundedValue = (int) Math.round(value);
SchemeEvaluateSchemeDetailOverallVO.OverallMetrics metric = new SchemeEvaluateSchemeDetailOverallVO.OverallMetrics();
metric.setMetricCode(metricEnum.getCode());
metric.setMetricUnit(metricEnum.getUnit());
metric.setMetricName(metricEnum.getDescription());
metric.setMetricValue(roundedValue);
return metric;
}
private List<CrossDirDataHistPO> getCrossDirDataHistPOList(Date startTime, Date newEndTime, String crossId) {
int startTimeStamp = (int) (startTime.getTime() / 1000);
int endTimeStamp = (int) (newEndTime.getTime() / 1000);
List<CrossDirDataHistPO> res = crossDirDataHistMapper.selectByCrossIdAndStartEnd(
crossId, startTimeStamp, endTimeStamp);
return res;
}
private Integer calcCrossFlow(List<CrossDataHistPO> crossDataHistPOList) {
int max = crossDataHistPOList.stream()
.mapToInt(CrossDataHistPO::getFlow)
.max()
.orElse(0);
return max;
}
private Double calcCrossSaturation(List<CrossDataHistPO> crossDataHistPOList) {
double max = crossDataHistPOList.stream()
.mapToDouble(CrossDataHistPO::getSturation)
.max()
.orElse(0.0);
return max;
}
private List<CrossDataHistPO> getCrossDataHistPOList(Date startTime, Date newEndTime, String crossId) {
int startTimeStamp = (int) (startTime.getTime() / 1000);
int endTimeStamp = (int) (newEndTime.getTime() / 1000);
List<CrossDataHistPO> crossDataHistPOList = crossDataHistMapper.selectByCrossIdAndStartEnd(
crossId, startTimeStamp, endTimeStamp);
return crossDataHistPOList;
}
private Integer calcCrossDelayTime(List<CrossDataHistPO> crossDataHistPOList) {
int max = crossDataHistPOList.stream()
.mapToInt(CrossDataHistPO::getDelayTime)
.max()
.orElse(0);
return max;
}
private List<String> buildPatternNames(List<BaseCrossSchemePO> matchedSchemes) {
List<String> res = new ArrayList<>();
for (BaseCrossSchemePO matchedScheme : matchedSchemes) {
res.add(matchedScheme.getName());
}
return res;
}
private List<Integer> buildDirs(String congestionDirs) {
List<Integer> res = new ArrayList<>();
String[] split = congestionDirs.split(",");
for (String s : split) {
res.add(Integer.parseInt(s));
}
return res;
}
private Integer calcCongestionLevel(Integer delayTime) {
Integer res = null;
if (delayTime >= 145) {
res = 3;
} else if (delayTime >= 100) {
res = 2;
} else if (delayTime >= 55) {
res = 1;
} else {
res = 0;
}
return res;
} }
public List<SceneEvaluateAbnormalDistributeVO.TimeDateDistribution> buildFinalTimeDistributionList( public List<SceneEvaluateAbnormalDistributeVO.TimeDateDistribution> buildFinalTimeDistributionList(
......
package net.wanji.opt.vo; package net.wanji.opt.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.List;
/** /**
* @author Kent HAN * @author Kent HAN
* @date 2023/2/9 8:38 * @date 2023/2/9 8:38
...@@ -12,5 +17,49 @@ import lombok.NoArgsConstructor; ...@@ -12,5 +17,49 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@ApiModel(value = "SceneEvaluateAbnormalDetailVO", description = "异常事件详情") @ApiModel(value = "SceneEvaluateAbnormalDetailVO", description = "异常事件详情")
public class SceneEvaluateAbnormalDetailVO { public class SceneEvaluateAbnormalDetailVO {
@ApiModelProperty(value = "事件类型",notes = "0正常 1 失衡 2 拥堵 3 溢出 4 死锁")
private Integer status ;
@ApiModelProperty(name = "开始时间:yyyy-MM-dd HH:mm")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
private Date startTime ;
// todo 目前只有拥堵,后期扩展考虑增加字段
@ApiModelProperty(value = "等级",notes = "0畅通 1轻度 2中度 3严重")
private Integer level ;
@ApiModelProperty(name = "持续时长(单位:分钟)")
private Integer duration ;
@ApiModelProperty(value = "方向列表:1北;2东北;3东;4东南;5南;6西南;7西;8西北")
private List<Integer> dirs;
@ApiModelProperty(value = "配时方案列表")
private List<String> patternNames;
@ApiModelProperty(value = "路口服务水平")
String serviceLevel;
@ApiModelProperty(value = "路口流量")
private Integer flow;
@ApiModelProperty(value = "指标数据")
List<SchemeEvaluateSchemeDetailOverallVO.OverallMetrics> overallMetricsList;
@NoArgsConstructor
@Data
public static class OverallMetrics {
@ApiModelProperty(value = "指标编号")
String metricCode;
@ApiModelProperty(value = "指标名称")
String metricName;
@ApiModelProperty(value = "指标数值")
Integer metricValue;
@ApiModelProperty(value = "指标数值单位")
String metricUnit;
}
} }
...@@ -2,7 +2,7 @@ package net.wanji.utc.cache; ...@@ -2,7 +2,7 @@ package net.wanji.utc.cache;
import net.wanji.common.enums.BaseEnum; import net.wanji.common.enums.BaseEnum;
import net.wanji.common.framework.spring.ServiceBeanContext; import net.wanji.common.framework.spring.ServiceBeanContext;
import net.wanji.feign.service.common.UtcFeignCommon; import net.wanji.feign.service.common.FeignCommon;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -16,9 +16,9 @@ import java.util.Map; ...@@ -16,9 +16,9 @@ import java.util.Map;
@Component @Component
public class UtcFeignClientCache implements CommandLineRunner { public class UtcFeignClientCache implements CommandLineRunner {
public static final Map<String, UtcFeignCommon> utcFeignClientsMap = new HashMap<>(); public static final Map<String, FeignCommon> utcFeignClientsMap = new HashMap<>();
public UtcFeignCommon getUtcFeignClientService(String name) { public FeignCommon getUtcFeignClientService(String name) {
if (!utcFeignClientsMap.isEmpty()) { if (!utcFeignClientsMap.isEmpty()) {
return utcFeignClientsMap.get(name); return utcFeignClientsMap.get(name);
} }
...@@ -30,11 +30,11 @@ public class UtcFeignClientCache implements CommandLineRunner { ...@@ -30,11 +30,11 @@ public class UtcFeignClientCache implements CommandLineRunner {
} }
public void init() { public void init() {
Map<String, UtcFeignCommon> interfaceBeanMap = ServiceBeanContext.getInterfaceBeanMap(UtcFeignCommon.class); Map<String, FeignCommon> interfaceBeanMap = ServiceBeanContext.getInterfaceBeanMap(FeignCommon.class);
if (!interfaceBeanMap.isEmpty()) { if (!interfaceBeanMap.isEmpty()) {
for (Map.Entry<String, UtcFeignCommon> item : interfaceBeanMap.entrySet()) { for (Map.Entry<String, FeignCommon> item : interfaceBeanMap.entrySet()) {
String feignName = item.getKey(); String feignName = item.getKey();
UtcFeignCommon utcFeignClientService = item.getValue(); FeignCommon utcFeignClientService = item.getValue();
for (BaseEnum.VendorTypeEnum value : BaseEnum.VendorTypeEnum.values()) { for (BaseEnum.VendorTypeEnum value : BaseEnum.VendorTypeEnum.values()) {
if (feignName.contains(value.getNick())) { if (feignName.contains(value.getNick())) {
utcFeignClientsMap.put(value.getNick(), utcFeignClientService); utcFeignClientsMap.put(value.getNick(), utcFeignClientService);
......
...@@ -3,7 +3,7 @@ package net.wanji.utc.service.control.impl; ...@@ -3,7 +3,7 @@ package net.wanji.utc.service.control.impl;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.wanji.common.framework.rest.JsonViewObject; import net.wanji.common.framework.rest.JsonViewObject;
import net.wanji.databus.vo.*; import net.wanji.databus.vo.*;
import net.wanji.feign.service.common.UtcFeignCommon; import net.wanji.feign.service.common.FeignCommon;
import net.wanji.utc.cache.CrossInfoCache; import net.wanji.utc.cache.CrossInfoCache;
import net.wanji.utc.cache.UtcFeignClientCache; import net.wanji.utc.cache.UtcFeignClientCache;
import net.wanji.utc.common.constant.Constants; import net.wanji.utc.common.constant.Constants;
...@@ -103,7 +103,7 @@ public class WanJiControlCommandServiceImpl implements ControlCommandService { ...@@ -103,7 +103,7 @@ public class WanJiControlCommandServiceImpl implements ControlCommandService {
@Override @Override
public JsonViewObject setSignalControl(String crossId, Integer command, Integer commandType) throws Exception { public JsonViewObject setSignalControl(String crossId, Integer command, Integer commandType) throws Exception {
String manufacturerIdCode = crossInfoCache.getManufacturerCodeByCrossId(crossId); String manufacturerIdCode = crossInfoCache.getManufacturerCodeByCrossId(crossId);
UtcFeignCommon utcFeignClientService = utcFeignClientCache.getUtcFeignClientService(manufacturerIdCode); FeignCommon utcFeignClientService = utcFeignClientCache.getUtcFeignClientService(manufacturerIdCode);
JsonViewObject jsonViewObject = JsonViewObject.newInstance(); JsonViewObject jsonViewObject = JsonViewObject.newInstance();
ControlCommandVO controlCommandVO = new ControlCommandVO(); ControlCommandVO controlCommandVO = new ControlCommandVO();
controlCommandVO.setCrossCode(crossId); controlCommandVO.setCrossCode(crossId);
......
...@@ -43,7 +43,8 @@ public class StrategyAndMetricsEnum { ...@@ -43,7 +43,8 @@ public class StrategyAndMetricsEnum {
LOAD_BALANCE("9", "负载均衡度", "", "loadBalance"), LOAD_BALANCE("9", "负载均衡度", "", "loadBalance"),
EFFUSION_RATE("10", "溢流率", "%", "effusionRate"), EFFUSION_RATE("10", "溢流率", "%", "effusionRate"),
CLEAR_RATE("11", "绿灯间隔清空率", "%", "clearRate"), CLEAR_RATE("11", "绿灯间隔清空率", "%", "clearRate"),
EMERGENCY_COUNT("12", "三急一速数量", "", "emergencyCount"); EMERGENCY_COUNT("12", "三急一速数量", "", "emergencyCount"),
EMPTY_DISCHARGES("13", "空放次数", "次", "emptyDischarges");
private final String code; private final String code;
private final String description; private final String description;
......
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