|
@@ -0,0 +1,487 @@
|
|
|
|
|
+package com.hdkj.lt.si.service.recon.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
+
|
|
|
|
|
+import com.hdkj.lt.base.exception.ExceptionCast;
|
|
|
|
|
+import com.hdkj.lt.core.bizms.modle.dto.StateEstimation;
|
|
|
|
|
+import com.hdkj.lt.core.rest.service.IRemoteCallService;
|
|
|
|
|
+import com.hdkj.lt.si.dao.*;
|
|
|
|
|
+import com.hdkj.lt.si.modle.dto.*;
|
|
|
|
|
+import com.hdkj.lt.si.service.recon.ReconResultService;
|
|
|
|
|
+import com.hdkj.lt.si.service.remote.impl.PsrDeviceRemoteCallServiceImpl;
|
|
|
|
|
+import com.hdkj.lt.si.service.remote.impl.ReconRemoteCallServiceImpl;
|
|
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
|
|
+import com.hdkj.lt.si.modle.*;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.core.io.ClassPathResource;
|
|
|
|
|
+import org.springframework.http.HttpEntity;
|
|
|
|
|
+import org.springframework.http.HttpMethod;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
+import org.springframework.util.StreamUtils;
|
|
|
|
|
+
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.OffsetDateTime;
|
|
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.function.BiConsumer;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 重构结果入库服务实现.
|
|
|
|
|
+ * 单事务写入主表 + 7 子表, 任一失败全部回滚.
|
|
|
|
|
+ * 类型转换: String(ISO8601)->LocalDateTime, JsonNode->JSON串, Boolean->tinyint(由MP处理), 数值->BigDecimal.
|
|
|
|
|
+ */
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+@Service
|
|
|
|
|
+@RequiredArgsConstructor
|
|
|
|
|
+public class ReconResultServiceImpl implements ReconResultService {
|
|
|
|
|
+
|
|
|
|
|
+ private final FhzgReconResultMapper resultMapper;
|
|
|
|
|
+ private final FhzgReconSwitchOpMapper switchOpMapper;
|
|
|
|
|
+ private final FhzgReconSwitchSeqMapper switchSeqMapper;
|
|
|
|
|
+ private final FhzgReconFeederResultMapper feederResultMapper;
|
|
|
|
|
+ private final FhzgReconVolResultMapper volResultMapper;
|
|
|
|
|
+ private final FhzgReconVolDetailMapper volDetailMapper;
|
|
|
|
|
+ private final FhzgReconSwitchResultDetailMapper switchResultDetailMapper;
|
|
|
|
|
+ private final FhzgReconMetricsMapper metricsMapper;
|
|
|
|
|
+
|
|
|
|
|
+ private static final ObjectMapper OM = new ObjectMapper()
|
|
|
|
|
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
|
|
|
|
+ private static final DateTimeFormatter ISO_OFFSET = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
|
|
|
|
|
+
|
|
|
|
|
+ private static final String REQUEST_URI = "http://25.91.249.219:18080/api/reconfiguration";
|
|
|
|
|
+ @Resource(type = ReconRemoteCallServiceImpl.class)
|
|
|
|
|
+ private IRemoteCallService remoteCallService;
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
+ public void saveReconResult(String eventId, List<String> feederIds) {
|
|
|
|
|
+ // 1. 构造请求参数
|
|
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
|
|
+// params.put("county_sid", "honghu");
|
|
|
|
|
+// params.put("county_name", "honghu");
|
|
|
|
|
+// params.put("problem_feeder_ids", Collections.singletonList("15DKX-20690"));
|
|
|
|
|
+ String str;
|
|
|
|
|
+ RawResultDTO dto;
|
|
|
|
|
+ try {
|
|
|
|
|
+ Object data = remoteCallService.call(REQUEST_URI, HttpMethod.POST, params, Object.class);
|
|
|
|
|
+ str = JSON.toJSONString(data);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 解析返回的JSON数据
|
|
|
|
|
+// try {
|
|
|
|
|
+// str = StreamUtils.copyToString(new ClassPathResource("1.txt").getInputStream(), StandardCharsets.UTF_8);
|
|
|
|
|
+// } catch (IOException e) {
|
|
|
|
|
+// throw new RuntimeException("读取算法响应样本 1.txt 失败", e);
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+ JsonNode root = OM.readTree(str);
|
|
|
|
|
+ log.info("重构方案接口返回参数{}",str);
|
|
|
|
|
+ JsonNode rawNode = root.get("raw_result");
|
|
|
|
|
+ if (rawNode == null || rawNode.isNull()) {
|
|
|
|
|
+ throw new RuntimeException("算法响应缺少 raw_result 节点");
|
|
|
|
|
+ }
|
|
|
|
|
+ dto = OM.treeToValue(rawNode, RawResultDTO.class);
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ throw new RuntimeException("解析算法响应 raw_result 失败", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Integer> counts = new LinkedHashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 主表
|
|
|
|
|
+ FhzgReconResult main = buildMain(dto);
|
|
|
|
|
+ main.setEventId(eventId);
|
|
|
|
|
+ resultMapper.insert(main);
|
|
|
|
|
+ Long resultId = main.getId();
|
|
|
|
|
+ counts.put("result", 1);
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 开关操作(简化版)
|
|
|
|
|
+ if (dto.getSwitchOp() != null) {
|
|
|
|
|
+ int n = insertSwitchOp(dto.getSwitchOp(), resultId);
|
|
|
|
|
+ counts.put("switch_op", n);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 开关操作序列(详细)
|
|
|
|
|
+ if (dto.getSwitchSeq() != null) {
|
|
|
|
|
+ int n = insertSwitchSeq(dto.getSwitchSeq(), resultId);
|
|
|
|
|
+ counts.put("switch_seq", n);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 馈线结果
|
|
|
|
|
+ if (dto.getFeederResult() != null) {
|
|
|
|
|
+ int n = insertFeederResult(dto.getFeederResult(), resultId);
|
|
|
|
|
+ counts.put("feeder_result", n);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 电压结果(汇总+详情)
|
|
|
|
|
+ if (dto.getVolResult() != null) {
|
|
|
|
|
+ if (dto.getVolResult().getSummary() != null) {
|
|
|
|
|
+ volResultMapper.insert(buildVolResult(dto.getVolResult().getSummary(), resultId));
|
|
|
|
|
+ counts.put("vol_result", 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dto.getVolResult().getDetails() != null) {
|
|
|
|
|
+ int n = insertVolDetail(dto.getVolResult().getDetails(), resultId);
|
|
|
|
|
+ counts.put("vol_detail", n);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 开关状态详情(summary 折叠进主表)
|
|
|
|
|
+ if (dto.getSwitchResult() != null && dto.getSwitchResult().getDetails() != null) {
|
|
|
|
|
+ int n = insertSwitchResultDetail(dto.getSwitchResult().getDetails(), resultId);
|
|
|
|
|
+ counts.put("switch_result_detail", n);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 7. 运行指标
|
|
|
|
|
+ if (dto.getMetrics() != null) {
|
|
|
|
|
+ metricsMapper.insert(buildMetrics(dto.getMetrics(), resultId));
|
|
|
|
|
+ counts.put("metrics", 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("重构方案counts:{}", JSON.toJSONString(counts));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 构建主表 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private FhzgReconResult buildMain(RawResultDTO dto) {
|
|
|
|
|
+ FhzgReconResult m = new FhzgReconResult();
|
|
|
|
|
+ m.setGroupId(dto.getGroupId());
|
|
|
|
|
+ m.setGroupSid(dto.getGroupSid());
|
|
|
|
|
+ m.setGroupName(dto.getGroupName());
|
|
|
|
|
+ m.setStAreaId(dto.getStAreaId());
|
|
|
|
|
+ m.setStatus(dto.getStatus());
|
|
|
|
|
+ m.setAlgo(dto.getAlgo());
|
|
|
|
|
+ m.setComputeResult(dto.getComputeResult());
|
|
|
|
|
+ m.setDetalDesc(dto.getDetalDesc());
|
|
|
|
|
+
|
|
|
|
|
+ // finalCheck 折叠
|
|
|
|
|
+ if (dto.getFinalCheck() != null) {
|
|
|
|
|
+ m.setFinalCheckIsSafe(dto.getFinalCheck().getSafe());
|
|
|
|
|
+ m.setFinalCheckDetails(dto.getFinalCheck().getDetails());
|
|
|
|
|
+ }
|
|
|
|
|
+ // switchResult.summary 折叠
|
|
|
|
|
+ if (dto.getSwitchResult() != null) {
|
|
|
|
|
+ m.setSwitchResultSummary(dto.getSwitchResult().getSummary());
|
|
|
|
|
+ }
|
|
|
|
|
+ m.setSnapshotTime(LocalDateTime.now());
|
|
|
|
|
+ return m;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 开关操作(简化版) ====================
|
|
|
|
|
+
|
|
|
|
|
+ private int insertSwitchOp(SwitchOpDTO dto, Long resultId) {
|
|
|
|
|
+ if (dto.getListSwitchOp() == null) return 0;
|
|
|
|
|
+ int i = 1;
|
|
|
|
|
+ for (BreakerOpDTO b : dto.getListSwitchOp()) {
|
|
|
|
|
+ FhzgReconSwitchOp e = new FhzgReconSwitchOp();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setOpNo(i++);
|
|
|
|
|
+ e.setBreakerId(b.getBreakerId());
|
|
|
|
|
+ e.setName(b.getName());
|
|
|
|
|
+ e.setPsrType(b.getPsrType());
|
|
|
|
|
+ e.setAutoType(b.getAutoType());
|
|
|
|
|
+ e.setOperationType(b.getOperationType());
|
|
|
|
|
+ e.setTimestamp(parseTime(b.getTimestamp()));
|
|
|
|
|
+ switchOpMapper.insert(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 开关操作序列(详细, 扁平) ====================
|
|
|
|
|
+
|
|
|
|
|
+ private int insertSwitchSeq(SwitchSeqDTO dto, Long resultId) {
|
|
|
|
|
+ if (dto.getListSwitchOp() == null) return 0;
|
|
|
|
|
+ int i = 0;
|
|
|
|
|
+ for (SwitchSeqDTO.SwitchSeqItemDTO it : dto.getListSwitchOp()) {
|
|
|
|
|
+ FhzgReconSwitchSeq e = new FhzgReconSwitchSeq();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setSeqNo(i++);
|
|
|
|
|
+ fillBreaker(e, it.getCloseBreakerOp(), true);
|
|
|
|
|
+ fillBreaker(e, it.getOpenBreakerOp(), false);
|
|
|
|
|
+ HotCheckDTO h = it.getHotCheck();
|
|
|
|
|
+ if (h != null) {
|
|
|
|
|
+ e.setHotCheckIsSafe(h.getSafe());
|
|
|
|
|
+ e.setHotCheckReason(h.getReason());
|
|
|
|
|
+ }
|
|
|
|
|
+ fillFeeder(e, it.getFeederIn(), true);
|
|
|
|
|
+ fillFeeder(e, it.getFeederOut(), false);
|
|
|
|
|
+ e.setDeltaLoss(it.getDeltaLoss());
|
|
|
|
|
+ e.setDeltaI(it.getDeltaI());
|
|
|
|
|
+ switchSeqMapper.insert(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void fillBreaker(FhzgReconSwitchSeq e, BreakerOpDTO b, boolean close) {
|
|
|
|
|
+ if (b == null) return;
|
|
|
|
|
+ if (close) {
|
|
|
|
|
+ e.setCloseBreakerId(b.getBreakerId());
|
|
|
|
|
+ e.setCloseName(b.getName());
|
|
|
|
|
+ e.setClosePsrType(b.getPsrType());
|
|
|
|
|
+ e.setCloseAutoType(b.getAutoType());
|
|
|
|
|
+ e.setCloseOperationType(b.getOperationType());
|
|
|
|
|
+ e.setCloseTimestamp(parseTime(b.getTimestamp()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ e.setOpenBreakerId(b.getBreakerId());
|
|
|
|
|
+ e.setOpenName(b.getName());
|
|
|
|
|
+ e.setOpenPsrType(b.getPsrType());
|
|
|
|
|
+ e.setOpenAutoType(b.getAutoType());
|
|
|
|
|
+ e.setOpenOperationType(b.getOperationType());
|
|
|
|
|
+ e.setOpenTimestamp(parseTime(b.getTimestamp()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void fillFeeder(FhzgReconSwitchSeq e, FeederFlowDTO f, boolean in) {
|
|
|
|
|
+ if (f == null) return;
|
|
|
|
|
+ if (in) {
|
|
|
|
|
+ e.setFeederInPsrId(f.getPsrId());
|
|
|
|
|
+ e.setFeederInPsrType(f.getPsrType());
|
|
|
|
|
+ e.setFeederInName(f.getName());
|
|
|
|
|
+ e.setFeederInRateCurrent(f.getRateCurrent());
|
|
|
|
|
+ e.setFeederInBeforeI(f.getBeforeI());
|
|
|
|
|
+ e.setFeederInAfterI(f.getAfterI());
|
|
|
|
|
+ e.setFeederInBeforeDayI(f.getBeforeDayI());
|
|
|
|
|
+ e.setFeederInAfterDayI(f.getAfterDayI());
|
|
|
|
|
+ e.setFeederInLineLossBefore(f.getLineLossBefore());
|
|
|
|
|
+ e.setFeederInLineLossAfter(f.getLineLossAfter());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ e.setFeederOutPsrId(f.getPsrId());
|
|
|
|
|
+ e.setFeederOutPsrType(f.getPsrType());
|
|
|
|
|
+ e.setFeederOutName(f.getName());
|
|
|
|
|
+ e.setFeederOutRateCurrent(f.getRateCurrent());
|
|
|
|
|
+ e.setFeederOutBeforeI(f.getBeforeI());
|
|
|
|
|
+ e.setFeederOutAfterI(f.getAfterI());
|
|
|
|
|
+ e.setFeederOutBeforeDayI(f.getBeforeDayI());
|
|
|
|
|
+ e.setFeederOutAfterDayI(f.getAfterDayI());
|
|
|
|
|
+ e.setFeederOutLineLossBefore(f.getLineLossBefore());
|
|
|
|
|
+ e.setFeederOutLineLossAfter(f.getLineLossAfter());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 馈线结果 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private int insertFeederResult(FeederResultDTO dto, Long resultId) {
|
|
|
|
|
+ if (dto.getListFeeder() == null) return 0;
|
|
|
|
|
+ int i = 1;
|
|
|
|
|
+ for (FeederFlowDTO f : dto.getListFeeder()) {
|
|
|
|
|
+ FhzgReconFeederResult e = new FhzgReconFeederResult();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setFeederNo(i++);
|
|
|
|
|
+ e.setPsrId(f.getPsrId());
|
|
|
|
|
+ e.setPsrType(f.getPsrType());
|
|
|
|
|
+ e.setName(f.getName());
|
|
|
|
|
+ e.setRateCurrent(f.getRateCurrent());
|
|
|
|
|
+ e.setBeforeI(f.getBeforeI());
|
|
|
|
|
+ e.setAfterI(f.getAfterI());
|
|
|
|
|
+ e.setBeforeDayI(f.getBeforeDayI());
|
|
|
|
|
+ e.setAfterDayI(f.getAfterDayI());
|
|
|
|
|
+ e.setLineLossBefore(f.getLineLossBefore());
|
|
|
|
|
+ e.setLineLossAfter(f.getLineLossAfter());
|
|
|
|
|
+ feederResultMapper.insert(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 电压结果-汇总 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private FhzgReconVolResult buildVolResult(VolResultDTO.VolSummaryDTO s, Long resultId) {
|
|
|
|
|
+ FhzgReconVolResult e = new FhzgReconVolResult();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setCommentText(s.getComment());
|
|
|
|
|
+ e.setVlimitMax(s.getVlimitMax());
|
|
|
|
|
+ e.setVlimitMin(s.getVlimitMin());
|
|
|
|
|
+ e.setLoadCount(s.getLoadCount());
|
|
|
|
|
+ e.setLoadCountMvtran(s.getLoadCountMvtran());
|
|
|
|
|
+ e.setLoadCountMvcustomer(s.getLoadCountMvcustomer());
|
|
|
|
|
+ e.setLoadCountMvpv(s.getLoadCountMvpv());
|
|
|
|
|
+ fillVolExtremes(e, s.getBefore(), true);
|
|
|
|
|
+ fillVolExtremes(e, s.getAfter(), false);
|
|
|
|
|
+ return e;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void fillVolExtremes(FhzgReconVolResult e, VolExtremesDTO x, boolean before) {
|
|
|
|
|
+ if (x == null) return;
|
|
|
|
|
+ if (before) {
|
|
|
|
|
+ e.setBeforeMaxVol(x.getMaxVol());
|
|
|
|
|
+ e.setBeforeOverMaxCount(x.getOverMaxCount());
|
|
|
|
|
+ e.setBeforeOverMaxList(toJson(x.getOverMaxList()));
|
|
|
|
|
+ e.setBeforeMinVol(x.getMinVol());
|
|
|
|
|
+ e.setBeforeUnderMinCount(x.getUnderMinCount());
|
|
|
|
|
+ e.setBeforeUnderMinList(toJson(x.getUnderMinList()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ e.setAfterMaxVol(x.getMaxVol());
|
|
|
|
|
+ e.setAfterOverMaxCount(x.getOverMaxCount());
|
|
|
|
|
+ e.setAfterOverMaxList(toJson(x.getOverMaxList()));
|
|
|
|
|
+ e.setAfterMinVol(x.getMinVol());
|
|
|
|
|
+ e.setAfterUnderMinCount(x.getUnderMinCount());
|
|
|
|
|
+ e.setAfterUnderMinList(toJson(x.getUnderMinList()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 电压结果-节点详情 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private int insertVolDetail(List<VolResultDTO.VolDetailDTO> details, Long resultId) {
|
|
|
|
|
+ int i = 1;
|
|
|
|
|
+ for (VolResultDTO.VolDetailDTO d : details) {
|
|
|
|
|
+ FhzgReconVolDetail e = new FhzgReconVolDetail();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setDetailNo(i++);
|
|
|
|
|
+ e.setPsrId(d.getPsrId());
|
|
|
|
|
+ e.setPsrType(d.getPsrType());
|
|
|
|
|
+ e.setName(d.getName());
|
|
|
|
|
+ e.setLoadType(d.getLoadType());
|
|
|
|
|
+ e.setBeforeU(d.getBeforeU());
|
|
|
|
|
+ e.setAfterU(d.getAfterU());
|
|
|
|
|
+ e.setBeforeUlv(d.getBeforeUlv());
|
|
|
|
|
+ e.setAfterUlv(d.getAfterUlv());
|
|
|
|
|
+ e.setBeforeP(d.getBeforeP());
|
|
|
|
|
+ e.setBeforeQ(d.getBeforeQ());
|
|
|
|
|
+ volDetailMapper.insert(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 开关状态-详情 ====================
|
|
|
|
|
+
|
|
|
|
|
+ private int insertSwitchResultDetail(List<SwitchResultDTO.SwitchResultDetailDTO> details, Long resultId) {
|
|
|
|
|
+ int i = 1;
|
|
|
|
|
+ for (SwitchResultDTO.SwitchResultDetailDTO d : details) {
|
|
|
|
|
+ FhzgReconSwitchResultDetail e = new FhzgReconSwitchResultDetail();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ e.setDetailNo(i++);
|
|
|
|
|
+ e.setPsrId(d.getPsrId());
|
|
|
|
|
+ e.setPsrType(d.getPsrType());
|
|
|
|
|
+ e.setNode1Rdfid(d.getNode1Rdfid());
|
|
|
|
|
+ e.setNode2Rdfid(d.getNode2Rdfid());
|
|
|
|
|
+ e.setAutoType(d.getAutoType());
|
|
|
|
|
+ e.setBeforeState(d.getBeforeState());
|
|
|
|
|
+ e.setBeforeI(d.getBeforeI());
|
|
|
|
|
+ e.setBeforeU(d.getBeforeU());
|
|
|
|
|
+ e.setAfterState(d.getAfterState());
|
|
|
|
|
+ e.setAfterI(d.getAfterI());
|
|
|
|
|
+ e.setAfterU(d.getAfterU());
|
|
|
|
|
+ switchResultDetailMapper.insert(e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return i;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 运行指标(扁平 + JSON) ====================
|
|
|
|
|
+
|
|
|
|
|
+ private FhzgReconMetrics buildMetrics(MetricsDTO dto, Long resultId) {
|
|
|
|
|
+ FhzgReconMetrics e = new FhzgReconMetrics();
|
|
|
|
|
+ e.setResultId(resultId);
|
|
|
|
|
+ fillMetricsSide(e, dto.getMetricsBefore(), true);
|
|
|
|
|
+ fillMetricsSide(e, dto.getMetricsAfter(), false);
|
|
|
|
|
+ e.setDelta(toJson(dto.getDelta()));
|
|
|
|
|
+ e.setJudgement(toJson(dto.getJudgement()));
|
|
|
|
|
+ return e;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 按 before/after 将指标子对象扁平写入实体对应字段; val 为 null 时跳过. */
|
|
|
|
|
+ private void fillMetricsSide(FhzgReconMetrics e, MetricsDTO.MetricsBeforeAfterDTO m, boolean before) {
|
|
|
|
|
+ if (m == null) return;
|
|
|
|
|
+
|
|
|
|
|
+ MetricsDTO.LoadingDTO ld = m.getLoading();
|
|
|
|
|
+ if (ld != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLineCount, FhzgReconMetrics::setAfterLoadingLineCount, ld.getLineCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingExtGridCount, FhzgReconMetrics::setAfterLoadingExtGridCount, ld.getExtGridCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingMaxLoadingPct, FhzgReconMetrics::setAfterLoadingMaxLoadingPct, ld.getMaxLoadingPct());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingAvgLoadingPct, FhzgReconMetrics::setAfterLoadingAvgLoadingPct, ld.getAvgLoadingPct());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingOverLimitCount, FhzgReconMetrics::setAfterLoadingOverLimitCount, ld.getOverLimitCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLoadingLimitPct, FhzgReconMetrics::setAfterLoadingLoadingLimitPct, ld.getLoadingLimitPct());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingUnit, FhzgReconMetrics::setAfterLoadingUnit, ld.getUnit());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLoadingSource, FhzgReconMetrics::setAfterLoadingLoadingSource, ld.getLoadingSource());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeFeederLoadRatesPct, FhzgReconMetrics::setAfterFeederLoadRatesPct, toJson(ld.getFeederLoadRatesPct()));
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLineMaxLoadingPct, FhzgReconMetrics::setAfterLoadingLineMaxLoadingPct, ld.getLineMaxLoadingPct());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLineAvgLoadingPct, FhzgReconMetrics::setAfterLoadingLineAvgLoadingPct, ld.getLineAvgLoadingPct());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLoadingLineOverLimitCount, FhzgReconMetrics::setAfterLoadingLineOverLimitCount, ld.getLineOverLimitCount());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MetricsDTO.LossDTO ls = m.getLoss();
|
|
|
|
|
+ if (ls != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLossLineLossMw, FhzgReconMetrics::setAfterLossLineLossMw, ls.getLineLossMw());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLossTrafoLossMw, FhzgReconMetrics::setAfterLossTrafoLossMw, ls.getTrafoLossMw());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLossTotalLossMw, FhzgReconMetrics::setAfterLossTotalLossMw, ls.getTotalLossMw());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeLossUnit, FhzgReconMetrics::setAfterLossUnit, ls.getUnit());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MetricsDTO.VoltageDTO v = m.getVoltage();
|
|
|
|
|
+ if (v != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageMinVmPu, FhzgReconMetrics::setAfterVoltageMinVmPu, v.getMinVmPu());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageMaxVmPu, FhzgReconMetrics::setAfterVoltageMaxVmPu, v.getMaxVmPu());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageAvgVmPu, FhzgReconMetrics::setAfterVoltageAvgVmPu, v.getAvgVmPu());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageUnderVminCount, FhzgReconMetrics::setAfterVoltageUnderVminCount, v.getUnderVminCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageOverVmaxCount, FhzgReconMetrics::setAfterVoltageOverVmaxCount, v.getOverVmaxCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageVminPu, FhzgReconMetrics::setAfterVoltageVminPu, v.getVminPu());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageVmaxPu, FhzgReconMetrics::setAfterVoltageVmaxPu, v.getVmaxPu());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageBusCount, FhzgReconMetrics::setAfterVoltageBusCount, v.getBusCount());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeVoltageUnit, FhzgReconMetrics::setAfterVoltageUnit, v.getUnit());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MetricsDTO.ReliabilityDTO r = m.getReliability();
|
|
|
|
|
+ if (r != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeReliabilityEnabled, FhzgReconMetrics::setAfterReliabilityEnabled, r.getEnabled());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeReliabilityComment, FhzgReconMetrics::setAfterReliabilityComment, r.getComment());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ MetricsDTO.HealthDTO h = m.getHealth();
|
|
|
|
|
+ if (h != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthScore, FhzgReconMetrics::setAfterHealthScore, h.getScore());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthBase, FhzgReconMetrics::setAfterHealthBase, h.getBase());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthPenalty, FhzgReconMetrics::setAfterHealthPenalty, h.getPenalty());
|
|
|
|
|
+ ScoreItemsDTO w = h.getWeights();
|
|
|
|
|
+ if (w != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthWeightSafe, FhzgReconMetrics::setAfterHealthWeightSafe, w.getSafe());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthWeightVoltage, FhzgReconMetrics::setAfterHealthWeightVoltage, w.getVoltage());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthWeightLoss, FhzgReconMetrics::setAfterHealthWeightLoss, w.getLoss());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthWeightBalance, FhzgReconMetrics::setAfterHealthWeightBalance, w.getBalance());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthWeightRisk, FhzgReconMetrics::setAfterHealthWeightRisk, w.getRisk());
|
|
|
|
|
+ }
|
|
|
|
|
+ ScoreItemsDTO c = h.getComponents();
|
|
|
|
|
+ if (c != null) {
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthComponentSafe, FhzgReconMetrics::setAfterHealthComponentSafe, c.getSafe());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthComponentVoltage, FhzgReconMetrics::setAfterHealthComponentVoltage, c.getVoltage());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthComponentLoss, FhzgReconMetrics::setAfterHealthComponentLoss, c.getLoss());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthComponentBalance, FhzgReconMetrics::setAfterHealthComponentBalance, c.getBalance());
|
|
|
|
|
+ side(e, before, FhzgReconMetrics::setBeforeHealthComponentRisk, FhzgReconMetrics::setAfterHealthComponentRisk, c.getRisk());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** before 时调 beforeSetter, 否则调 afterSetter; val 为 null 跳过. */
|
|
|
|
|
+ private <T> void side(FhzgReconMetrics e, boolean before,
|
|
|
|
|
+ BiConsumer<FhzgReconMetrics, T> beforeSetter,
|
|
|
|
|
+ BiConsumer<FhzgReconMetrics, T> afterSetter, T val) {
|
|
|
|
|
+ if (val == null) return;
|
|
|
|
|
+ (before ? beforeSetter : afterSetter).accept(e, val);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 类型转换工具 ====================
|
|
|
|
|
+
|
|
|
|
|
+ /** ISO8601 字符串(含时区) -> LocalDateTime(取本地壁钟时间); 无法解析返回 null. */
|
|
|
|
|
+ private LocalDateTime parseTime(String s) {
|
|
|
|
|
+ if (s == null || s.trim().isEmpty()) return null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ return OffsetDateTime.parse(s, ISO_OFFSET).toLocalDateTime();
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ return LocalDateTime.parse(s, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
|
|
|
|
+ } catch (Exception e2) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** JsonNode -> JSON 字符串; null 或 null 节点返回 null. */
|
|
|
|
|
+ private String toJson(JsonNode node) {
|
|
|
|
|
+ if (node == null || node.isNull()) return null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ return OM.writeValueAsString(node);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|