| 
					
				 | 
			
			
				@@ -1,13 +1,33 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package com.jjt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ruoyi.RuoYiApplication; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.domain.TwinCalcAlarms; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.domain.TwinCalcDay; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.domain.TwinCalcHour; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.domain.TwinCalcStop; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.mapper.TwinCalcDayMapper; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.service.ITwinCalcAlarmsService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.ruoyi.biz.service.ITwinCalcDayService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.service.ITwinCalcHourService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.service.ITwinCalcStopService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.ruoyi.biz.tools.Tools; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import javafx.util.Pair; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.junit.jupiter.api.Test; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.boot.test.context.SpringBootTest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.springframework.jdbc.core.JdbcTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import javax.annotation.Resource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.math.BigDecimal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.math.RoundingMode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.time.LocalDate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.time.ZoneOffset; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Date; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.LinkedHashMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.List; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.atomic.AtomicLong; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.function.BiConsumer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.stream.Collectors; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * DataProcess$ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -21,6 +41,12 @@ public class CalcDayTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private JdbcTemplate jdbcTemplate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private ITwinCalcDayService dayService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private ITwinCalcHourService hourService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private ITwinCalcStopService stopService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Resource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private ITwinCalcAlarmsService alarmsService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static void main(String[] args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LocalDate localDate = LocalDate.parse("2024-06-27"); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -39,4 +65,117 @@ public class CalcDayTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //        dayService.calc4date(localDate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void test1() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        LocalDate localDate = LocalDate.parse("2024-06-27"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date date = Date.from(localDate.atStartOfDay(ZoneOffset.of("+8")).toInstant()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //计算统计时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Pair<Date, Date> pair = Tools.calcDay(localDate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date sTime = pair.getKey(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date eTime = pair.getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<TwinCalcHour> hourList = hourService.selectTwinCalcHourListByDate(sTime, eTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        hourList = hourList.stream().filter(d -> d.getDeviceId().equals(10L)).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<TwinCalcStop> stopList = stopService.selectTwinCalcStopListByDate(sTime, eTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        List<TwinCalcAlarms> alarmsList = alarmsService.selectTwinCalcAlarmsListByDate(sTime, eTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Pair<Date, Date> teamPairA = Tools.teamA(localDate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Pair<Date, Date> teamPairB = Tools.teamB(localDate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 提取A班和B班的开始和结束时间,避免在循环中重复调用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date startTimeA = teamPairA.getKey(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date endTimeA = teamPairA.getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date startTimeB = teamPairB.getKey(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Date endTimeB = teamPairB.getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Map<Long, List<TwinCalcHour>> hourDeviceGroup = hourList.stream().collect(Collectors.groupingBy(TwinCalcHour::getDeviceId, LinkedHashMap::new, Collectors.toList())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (Map.Entry<Long, List<TwinCalcHour>> entry : hourDeviceGroup.entrySet()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            List<TwinCalcHour> hours = entry.getValue(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            TwinCalcDay day = new TwinCalcDay(date); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setDeviceId(entry.getKey()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //计算产量数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.calcHours(hours); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //计算停机数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            List<TwinCalcStop> stops = stopList.stream().filter(s -> s.getDeviceId().equals(entry.getKey())).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            AtomicLong closeA = new AtomicLong(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            AtomicLong closeB = new AtomicLong(0L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //A班停机计数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BiConsumer<Integer, Integer> updateDayA = (type, count) -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                switch (type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop1A(day.getStop1A() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 2: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop2A(day.getStop2A() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 3: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop3A(day.getStop3A() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BiConsumer<Integer, Integer> updateDayB = (type, count) -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                switch (type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop1B(day.getStop1B() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 2: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop2B(day.getStop2B() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case 3: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        day.setStop3B(day.getStop3B() + count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 使用Stream API,结合if-else逻辑的优化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            stops.stream().forEach(stop -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 根据停机时间判断属于哪个班次 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                boolean isAshift = !stop.getStartTime().after(endTimeA) && !stop.getEndTime().before(startTimeA); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Date shiftStart = isAshift ? startTimeA : startTimeB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Date shiftEnd = isAshift ? endTimeA : endTimeB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                AtomicLong totalStopTime = isAshift ? closeA : closeB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                BiConsumer<Integer, Integer> eventCounter = isAshift ? updateDayA : updateDayB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 调整停机时间 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (stop.getEndTime().compareTo(shiftEnd) > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    stop.setEndTime(shiftEnd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (stop.getStartTime().compareTo(shiftStart) < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    stop.setStartTime(shiftStart); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 计算并更新停机时间和事件计数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                long stopTime = (stop.getEndTime().getTime() - stop.getStartTime().getTime()) / 1000; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                updateStopCounters(stopTime, stop.getStopType(), totalStopTime, eventCounter); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //计算稼动率 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //AB班排班时间,要乘以设备总数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long teamTimeA = 12L * 60 * 60; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long teamTimeB = 12L * 60 * 60; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long totalTeamTime = teamTimeA + teamTimeB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long openTimeA = teamTimeA - closeA.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long openTimeB = teamTimeB - closeB.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            long totalOpenTime = openTimeA + openTimeB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BigDecimal ea = BigDecimal.valueOf(openTimeA).divide(BigDecimal.valueOf(teamTimeA), 2, RoundingMode.HALF_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BigDecimal eb = BigDecimal.valueOf(openTimeB).divide(BigDecimal.valueOf(teamTimeB), 2, RoundingMode.HALF_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            BigDecimal ee = BigDecimal.valueOf(totalOpenTime).divide(BigDecimal.valueOf(totalTeamTime), 2, RoundingMode.HALF_UP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setOpenTimeA(BigDecimal.valueOf(openTimeA)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setOpenTimeB(BigDecimal.valueOf(openTimeB)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setCloseTimeA(BigDecimal.valueOf(closeA.get())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setCloseTimeB(BigDecimal.valueOf(closeB.get())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setEfficiencyA(ea); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setEfficiencyB(eb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setEfficiency(ee); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            List<TwinCalcAlarms> alarms = alarmsList.stream().filter(a -> a.getDeviceId().equals(entry.getKey())).collect(Collectors.toList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            day.setAlarm((long) alarms.size()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void updateStopCounters(long stopTime, int stopType, AtomicLong 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            totalTimeCounter, BiConsumer<Integer, Integer> eventCounterUpdater) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        totalTimeCounter.addAndGet(stopTime); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        eventCounterUpdater.accept(stopType, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |