¶Ô±ÈÐÂÎļþ |
| | |
| | | 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) { |
| | | String validDate = LocalDate.now().minusDays(1).toString().replaceAll("-", ""); |
| | | if (StringUtils.isNotBlank(dateTime)) { |
| | | validDate = DateUtils.format(DateUtils.toDate(dateTime, DateUtils.STRDATE), DateUtils.STRDATE); |
| | | } |
| | | try { |
| | | this.remove(new LambdaQueryWrapper<MdcEquipmentFaultInfo>().eq(MdcEquipmentFaultInfo::getTheDate, validDate)); |
| | | } catch (Exception e) { |
| | | log.error("åæ°æ ¼å¼ä¸å¯¹", e); |
| | | } |
| | | |
| | | List<Equipment> equipmentList = equipmentService.list(); |
| | | if (equipmentList == null || equipmentList.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | 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 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()); |
| | | 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)); |
| | | equFaultRecordMap.forEach((key, value) -> { |
| | | if (map.containsKey(key)) { |
| | | MdcEquipmentFaultInfo equFaultRecords = map.get(key); |
| | | long faultLong = calculateTotalFaultDuration(value, start, end); |
| | | equFaultRecords.setFaultLong((int) faultLong); |
| | | if (faultLong != 0) { |
| | | equFaultRecords.setFaultRate(new BigDecimal(faultLong).divide(new BigDecimal("86400"), 2, RoundingMode.HALF_UP)); |
| | | } |
| | | |
| | | // 计ç®å»é¤æ
éæ¶é¿çå å·¥æ¶é´ |
| | | // step.1 æ¥è¯¢å å·¥æ¶é´ |
| | | List<MdcEquipmentRunningSection> mdcEquipmentRunningSections = mdcEquipmentRunningSectionService.selectRunningData(key, start, end); |
| | | 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); |
| | | } |
| | | } |
| | | // step.2 计ç®å»é¤æ
éæ¶é¿çå å·¥æ¶é´ |
| | | long processingTime = calculateProcessingTimeWithoutFaults(mdcEquipmentRunningSections, value, start, end); |
| | | equFaultRecords.setRemoveFaultRunLong((int) processingTime); |
| | | if (faultLong != 0) { |
| | | // 计ç®å»é¤æ
éæ¶é¿çå©ç¨ç |
| | | BigDecimal removeFaultRate = new BigDecimal(processingTime).divide(new BigDecimal("86400").subtract(new BigDecimal(faultLong)), 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) { |
| | | |
| | | // 转æ¢ä¸ºLocalDateTimeè¿è¡å¤ç |
| | | LocalDateTime start = DateUtils.convertToLocalDateTime(startTime); |
| | | LocalDateTime end = DateUtils.convertToLocalDateTime(endTime); |
| | | |
| | | // å°æ
éè®°å½è½¬æ¢ä¸ºæ¶é´åºé´å¹¶åå¹¶éå é¨å |
| | | // List<TimeInterval> faultIntervals = faultRecords.stream() |
| | | // .map(record -> new TimeInterval( |
| | | // convertToLocalDateTime(record.getStartTime()), |
| | | // convertToLocalDateTime(record.getEndTime()))) |
| | | // .collect(Collectors.toList()); |
| | | List<TimeInterval> mergedFaultIntervals = mergeIntervals(faultRecords); |
| | | |
| | | 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())); |
| | | } |
| | | } |
| | | |
| | | } |