From 23855599412c4d61b38d78f0f3abd3430a48b5b1 Mon Sep 17 00:00:00 2001
From: zhangherong <571457620@qq.com>
Date: 星期三, 25 六月 2025 11:51:38 +0800
Subject: [PATCH] Merge branch 'mdc_hyjs_master'

---
 lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentFaultInfoServiceImpl.java |  348 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 348 insertions(+), 0 deletions(-)

diff --git a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentFaultInfoServiceImpl.java b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentFaultInfoServiceImpl.java
new file mode 100644
index 0000000..83fa48f
--- /dev/null
+++ b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEquipmentFaultInfoServiceImpl.java
@@ -0,0 +1,348 @@
+package org.jeecg.modules.mdc.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.apache.commons.lang.StringUtils;
+import org.jeecg.modules.mdc.entity.*;
+import org.jeecg.modules.mdc.mapper.MdcEquipmentFaultInfoMapper;
+import org.jeecg.modules.mdc.service.IEquipmentService;
+import org.jeecg.modules.mdc.service.IMdcEquipmentFaultInfoService;
+import org.jeecg.modules.mdc.service.IMdcEquipmentRunningSectionService;
+import org.jeecg.modules.mdc.service.IMdcSystemParametersService;
+import org.jeecg.modules.mdc.util.DateUtils;
+import org.jeecg.modules.mdc.vo.EquFaultRecord;
+import org.jeecg.modules.mdc.vo.TimeInterval;
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 鏁呴殰鐜囪〃
+ * @Author: Lius
+ * @Date: 2025-06-16
+ * @Version: V1.0
+ */
+@Service
+public class MdcEquipmentFaultInfoServiceImpl extends ServiceImpl<MdcEquipmentFaultInfoMapper, MdcEquipmentFaultInfo> implements IMdcEquipmentFaultInfoService {
+
+    @Resource
+    private IEquipmentService equipmentService;
+
+    @Resource
+    private IMdcSystemParametersService mdcSystemParametersService;
+
+    @Resource
+    private IMdcEquipmentRunningSectionService mdcEquipmentRunningSectionService;
+
+    @Override
+    @Transactional(rollbackFor = {Exception.class})
+    public void runningAllEquFaultStatistical(String dateTime) {
+        Date initDate = null;
+
+        if (StringUtils.isNotBlank(dateTime)) {
+            initDate = DateUtils.toDate(dateTime, DateUtils.STRDATE);
+        } else {
+            // 鍙栨渶鍚庣殑缁熻鏃堕棿
+            String date = this.baseMapper.getMaxStaticsData();
+            if (date != null) {
+                initDate = DateUtils.toDate(date, DateUtils.STRDATE);
+            } else {
+                // 鍒濇鍙栧�� 鍙栨渶鏃╂椂闂磋褰�
+                MdcEquipmentRunningSection equipmentRunningSection = mdcEquipmentRunningSectionService.getFirstRecord();
+                if (equipmentRunningSection != null) {
+                    initDate = equipmentRunningSection.getStartTime();
+                }
+            }
+        }
+        Date endDate = DateUtils.addDays(DateUtils.getNow(), -1);
+        List<String> dateList = DateUtils.getDatesStringList2(initDate, endDate);
+
+        if (dateList.isEmpty()) {
+            return;
+        }
+        try {
+            this.remove(new LambdaQueryWrapper<MdcEquipmentFaultInfo>().in(MdcEquipmentFaultInfo::getTheDate, dateList));
+        } catch (Exception e) {
+            log.error("鍙傛暟鏍煎紡涓嶅", e);
+        }
+
+        List<Equipment> equipmentList = equipmentService.list();
+        if (equipmentList == null || equipmentList.isEmpty()) {
+            return;
+        }
+
+        String planTime = "00:00:00";
+        MdcSystemParameters mdcSystemParameters = mdcSystemParametersService.getOne(new LambdaQueryWrapper<MdcSystemParameters>().eq(MdcSystemParameters::getCode, "equip_log_statis_time"));
+        if (mdcSystemParameters != null) {
+            planTime = mdcSystemParameters.getValue();
+        }
+
+        List<String> equipmentIdList = equipmentList.stream().map(Equipment::getEquipmentid).collect(Collectors.toList());
+
+        for (String validDate : dateList) {
+            Map<String, MdcEquipmentFaultInfo> map = new HashMap<>();
+            String finalValidDate = validDate;
+            equipmentList.forEach(equipment -> {
+                MdcEquipmentFaultInfo mdcEquipmentFaultInfo = new MdcEquipmentFaultInfo(equipment.getEquipmentid(), finalValidDate);
+                map.put(equipment.getEquipmentid(), mdcEquipmentFaultInfo);
+            });
+
+            String startTime = DateUtils.format(DateUtils.setTimeForDay(DateUtils.toDate(validDate, DateUtils.STRDATE), planTime), DateUtils.STR_DATE_TIME_SMALL);
+            Date start = DateUtils.toDate(startTime, DateUtils.STR_DATE_TIME_SMALL);
+            String endTime = DateUtils.format(DateUtils.addDays(DateUtils.toDate(startTime, DateUtils.STR_DATE_TIME_SMALL), 1), DateUtils.STR_DATE_TIME_SMALL);
+            Date end = DateUtils.toDate(endTime, DateUtils.STR_DATE_TIME_SMALL);
+            //鏌ヨ鏁呴殰璁板綍
+            List<EquFaultRecord> equFaultRecordList = this.baseMapper.findFaultRecord(equipmentIdList, startTime, endTime);
+            if (equFaultRecordList != null && !equFaultRecordList.isEmpty()) {
+                // 淇暣鏃堕棿
+                Map<String, List<EquFaultRecord>> equFaultRecordMap = equFaultRecordList.stream().collect(Collectors.groupingBy(EquFaultRecord::getEquipmentId));
+                map.forEach((key, value1) -> {
+                    MdcEquipmentFaultInfo equFaultRecords = value1;
+                    if (equFaultRecordMap.containsKey(key)) {
+                        List<EquFaultRecord> value = equFaultRecordMap.get(key);
+                        long faultLong = calculateTotalFaultDuration(value, start, end);
+                        equFaultRecords.setFaultLong((int) faultLong);
+                        if (faultLong != 0) {
+                            equFaultRecords.setFaultRate(new BigDecimal(faultLong).divide(new BigDecimal("864"), 2, RoundingMode.HALF_UP));
+                        }
+                        // 璁$畻鍘婚櫎鏁呴殰鏃堕暱鐨勫姞宸ユ椂闂�
+                        // step.1 鏌ヨ鍔犲伐鏃堕棿
+                        List<MdcEquipmentRunningSection> mdcEquipmentRunningSections = mdcEquipmentRunningSectionService.listEquipmentRunningSectionRun(key, start.getTime(), end.getTime());
+                        if (mdcEquipmentRunningSections != null && !mdcEquipmentRunningSections.isEmpty()) {
+                            // 鏃堕棿淇
+                            if (mdcEquipmentRunningSections.get(0).getStartTime().before(start)) {
+                                mdcEquipmentRunningSections.get(0).setStartTime(start);
+                            }
+                            if (mdcEquipmentRunningSections.size() > 1) {
+                                if (mdcEquipmentRunningSections.get(mdcEquipmentRunningSections.size() - 1).getEndTime().after(end)) {
+                                    mdcEquipmentRunningSections.get(mdcEquipmentRunningSections.size() - 1).setEndTime(end);
+                                }
+                            } else {
+                                if (mdcEquipmentRunningSections.get(0).getEndTime().after(end)) {
+                                    mdcEquipmentRunningSections.get(0).setEndTime(end);
+                                }
+                            }
+                            List<MdcEquipmentRunningSection> collect = mdcEquipmentRunningSections.stream().filter(mdcEquipmentRunningSection -> mdcEquipmentRunningSection.getStatus() == 3).collect(Collectors.toList());
+                            if (!collect.isEmpty()) {
+                                // step.2 璁$畻鍘婚櫎鏁呴殰鏃堕暱鐨勫姞宸ユ椂闂�
+                                long processingTime = calculateProcessingTimeWithoutFaults(collect, value, start, end);
+                                equFaultRecords.setRemoveFaultRunLong((int) processingTime);
+                                if (faultLong != 0 && faultLong != 86400) {
+                                    // 璁$畻鍘婚櫎鏁呴殰鏃堕暱鐨勫埄鐢ㄧ巼
+                                    BigDecimal removeFaultRate = new BigDecimal(processingTime).divide(new BigDecimal("864").subtract(new BigDecimal(faultLong)), 2, RoundingMode.HALF_UP);
+                                    equFaultRecords.setRemoveFaultRate(removeFaultRate);
+                                }
+                            }
+                        }
+                    } else {
+                        List<MdcEquipmentRunningSection> mdcEquipmentRunningSections = mdcEquipmentRunningSectionService.listEquipmentRunningSectionRun(key, start.getTime(), end.getTime());
+                        if (mdcEquipmentRunningSections != null && !mdcEquipmentRunningSections.isEmpty()) {
+                            // 鏃堕棿淇
+                            if (mdcEquipmentRunningSections.get(0).getStartTime().before(start)) {
+                                mdcEquipmentRunningSections.get(0).setStartTime(start);
+                            }
+                            if (mdcEquipmentRunningSections.size() > 1) {
+                                if (mdcEquipmentRunningSections.get(mdcEquipmentRunningSections.size() - 1).getEndTime().after(end)) {
+                                    mdcEquipmentRunningSections.get(mdcEquipmentRunningSections.size() - 1).setEndTime(end);
+                                }
+                            } else {
+                                if (mdcEquipmentRunningSections.get(0).getEndTime().after(end)) {
+                                    mdcEquipmentRunningSections.get(0).setEndTime(end);
+                                }
+                            }
+                            List<MdcEquipmentRunningSection> collect = mdcEquipmentRunningSections.stream().filter(mdcEquipmentRunningSection -> mdcEquipmentRunningSection.getStatus() == 3).collect(Collectors.toList());
+
+                            if (!collect.isEmpty()) {
+                                long totalProcessingTime = 0;
+                                for (MdcEquipmentRunningSection mdcEquipmentRunningSection : collect) {
+                                    totalProcessingTime += ChronoUnit.SECONDS.between(DateUtils.convertToLocalDateTime(mdcEquipmentRunningSection.getStartTime()), DateUtils.convertToLocalDateTime(mdcEquipmentRunningSection.getEndTime()));
+                                }
+                                equFaultRecords.setRemoveFaultRunLong((int) totalProcessingTime);
+                                // 璁$畻鍘婚櫎鏁呴殰鏃堕暱鐨勫埄鐢ㄧ巼
+                                BigDecimal removeFaultRate = new BigDecimal(totalProcessingTime).divide(new BigDecimal("864"), 2, RoundingMode.HALF_UP);
+                                equFaultRecords.setRemoveFaultRate(removeFaultRate);
+                            }
+                        }
+                    }
+                    map.put(key, equFaultRecords);
+                });
+            }
+            if (!map.isEmpty()) {
+                this.saveBatch(new ArrayList<>(map.values()));
+            }
+        }
+    }
+
+    public static long calculateTotalFaultDuration(List<EquFaultRecord> records, Date startTime, Date endTime) {
+        LocalDateTime start = DateUtils.convertToLocalDateTime(startTime);
+        LocalDateTime end = DateUtils.convertToLocalDateTime(endTime);
+
+        // 淇璁板綍鏃堕棿
+        List<EquFaultRecord> correctedRecords = correctRecordTimes(records, start, end);
+
+        // 鎸夊紑濮嬫椂闂存帓搴�
+        correctedRecords.sort(Comparator.comparing(EquFaultRecord::getStartTime));
+
+        // 鍚堝苟閲嶅彔鏃堕棿娈�
+        List<TimeInterval> mergedIntervals = mergeIntervals(correctedRecords);
+
+        // 璁$畻鎬绘椂闀匡紙绉掞級
+        return mergedIntervals.stream()
+                .mapToLong(interval -> ChronoUnit.SECONDS.between(interval.getStart(), interval.getEnd()))
+                .sum();
+    }
+
+    private static List<EquFaultRecord> correctRecordTimes(List<EquFaultRecord> records, LocalDateTime startTime, LocalDateTime endTime) {
+        return records.stream()
+                .map(record -> {
+                    LocalDateTime recordStart = DateUtils.convertToLocalDateTime(record.getStartTime());
+                    LocalDateTime recordEnd = record.getEndTime() != null ?
+                            DateUtils.convertToLocalDateTime(record.getEndTime()) : null;
+
+                    // 淇寮�濮嬫椂闂�
+                    LocalDateTime correctedStart = recordStart.isBefore(startTime) ?
+                            startTime : recordStart;
+
+                    // 淇缁撴潫鏃堕棿
+                    LocalDateTime correctedEnd = recordEnd == null || recordEnd.isAfter(endTime) ?
+                            endTime : recordEnd;
+
+                    // 鍒涘缓淇鍚庣殑璁板綍
+                    return new EquFaultRecord(
+                            record.getEquipmentId(),
+                            DateUtils.convertToDate(correctedStart),
+                            DateUtils.convertToDate(correctedEnd)
+                    );
+                })
+                .collect(Collectors.toList());
+    }
+
+    private static List<TimeInterval> mergeIntervals(List<EquFaultRecord> records) {
+        List<TimeInterval> intervals = records.stream()
+                .map(record -> new TimeInterval(
+                        DateUtils.convertToLocalDateTime(record.getStartTime()),
+                        DateUtils.convertToLocalDateTime(record.getEndTime())))
+                .collect(Collectors.toList());
+
+        if (intervals.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<TimeInterval> merged = new ArrayList<>();
+        TimeInterval current = intervals.get(0);
+
+        for (int i = 1; i < intervals.size(); i++) {
+            TimeInterval next = intervals.get(i);
+            if (next.getStart().isBefore(current.getEnd()) || next.getStart().equals(current.getEnd())) {
+                // 鏈夐噸鍙狅紝鍚堝苟鍖洪棿
+                current.setEnd(current.getEnd().isAfter(next.getEnd()) ? current.getEnd() : next.getEnd());
+            } else {
+                // 鏃犻噸鍙狅紝娣诲姞褰撳墠鍖洪棿骞舵洿鏂板綋鍓嶅尯闂�
+                merged.add(current);
+                current = next;
+            }
+        }
+        merged.add(current); // 娣诲姞鏈�鍚庝竴涓尯闂�
+
+        return merged;
+    }
+
+    // 璁$畻鍘婚櫎鏁呴殰鏃堕暱鍚庣殑鍔犲伐鏃堕棿
+    private long calculateProcessingTimeWithoutFaults(
+            List<MdcEquipmentRunningSection> runningSections,
+            List<EquFaultRecord> faultRecords,
+            Date startTime,
+            Date endTime) {
+
+        // 杞崲涓篖ocalDateTime杩涜澶勭悊
+        LocalDateTime start = DateUtils.convertToLocalDateTime(startTime);
+        LocalDateTime end = DateUtils.convertToLocalDateTime(endTime);
+
+        // 淇璁板綍鏃堕棿
+        List<EquFaultRecord> correctedRecords = correctRecordTimes(faultRecords, start, end);
+        List<TimeInterval> mergedFaultIntervals = mergeIntervals(correctedRecords);
+
+        long totalProcessingTime = 0;
+
+        // 閬嶅巻姣忎釜鍔犲伐鍖洪棿锛屾帓闄ゆ晠闅滄椂闂�
+        for (MdcEquipmentRunningSection section : runningSections) {
+            LocalDateTime sectionStart = DateUtils.convertToLocalDateTime(section.getStartTime());
+            LocalDateTime sectionEnd = DateUtils.convertToLocalDateTime(section.getEndTime());
+
+            // 鎺掗櫎鏁呴殰鏃堕棿鍚庣殑鏈夋晥鍔犲伐鏃堕棿
+            List<TimeInterval> validIntervals = excludeFaultsFromSection(
+                    new TimeInterval(sectionStart, sectionEnd),
+                    mergedFaultIntervals);
+
+            // 绱姞鏈夋晥鍔犲伐鏃堕棿锛堢锛�
+            for (TimeInterval interval : validIntervals) {
+                totalProcessingTime += ChronoUnit.SECONDS.between(interval.getStart(), interval.getEnd());
+            }
+        }
+
+        return totalProcessingTime;
+    }
+
+    // 浠庤繍琛屽尯闂翠腑鎺掗櫎鏁呴殰鏃堕棿
+    private List<TimeInterval> excludeFaultsFromSection(
+            TimeInterval section,
+            List<TimeInterval> faultIntervals) {
+
+        List<TimeInterval> validIntervals = new ArrayList<>();
+        validIntervals.add(section);
+
+        // 閬嶅巻姣忎釜鏁呴殰鍖洪棿锛屼粠鏈夋晥鍖洪棿涓墸闄�
+        for (TimeInterval fault : faultIntervals) {
+            List<TimeInterval> newValidIntervals = new ArrayList<>();
+
+            for (TimeInterval valid : validIntervals) {
+                // 璁$畻鏈夋晥鍖洪棿涓庢晠闅滃尯闂寸殑浜ら泦
+                if (isOverlapping(valid, fault)) {
+                    // 鍒嗗壊鏈夋晥鍖洪棿
+                    splitInterval(valid, fault, newValidIntervals);
+                } else {
+                    // 鏃犱氦闆嗭紝淇濈暀鍘熸湁鏁堝尯闂�
+                    newValidIntervals.add(valid);
+                }
+            }
+
+            validIntervals = newValidIntervals;
+        }
+
+        return validIntervals;
+    }
+
+    // 鍒ゆ柇涓や釜鏃堕棿鍖洪棿鏄惁閲嶅彔
+    private boolean isOverlapping(TimeInterval a, TimeInterval b) {
+        return a.getStart().isBefore(b.getEnd()) && b.getStart().isBefore(a.getEnd());
+    }
+
+    // 鍒嗗壊鍖洪棿锛堟墸闄ら噸鍙犻儴鍒嗭級
+    private void splitInterval(
+            TimeInterval valid,
+            TimeInterval fault,
+            List<TimeInterval> result) {
+
+        // 閲嶅彔鍓嶇殑閮ㄥ垎
+        if (valid.getStart().isBefore(fault.getStart())) {
+            result.add(new TimeInterval(valid.getStart(), fault.getStart()));
+        }
+
+        // 閲嶅彔鍚庣殑閮ㄥ垎
+        if (valid.getEnd().isAfter(fault.getEnd())) {
+            result.add(new TimeInterval(fault.getEnd(), valid.getEnd()));
+        }
+    }
+
+}

--
Gitblit v1.9.3