Sfoglia il codice sorgente

add pattern select

HANTE 5 mesi fa
parent
commit
0bfa3c7784
43 ha cambiato i file con 1098 aggiunte e 565 eliminazioni
  1. 87 4
      utic-common/src/main/java/com/utic/common/utils/TimeUtils.java
  2. 0 2
      utic-dwdb-server/src/main/java/com/utic/dwdb/server/dao/mapper/BatchDaoService.java
  3. 9 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/UticPtisServerApplication.java
  4. 24 0
      utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafEtlpController.java
  5. 23 30
      utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafPrcsController.java
  6. 0 47
      utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafPrcsPrepareController.java
  7. 0 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/BatchDaoService.java
  8. 2 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/DwdbParamMapper.java
  9. 2 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/DwdbTrafficMapper.java
  10. 7 7
      utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/LinkPatternMapper.java
  11. 20 0
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/DbmsBatchJobResult.java
  12. 0 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkCollectParam.java
  13. 34 6
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkDto.java
  14. 7 7
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkMissingValueHistDto.java
  15. 15 0
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkPatternParam.java
  16. 24 6
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkTrafCenterDto.java
  17. 14 16
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkTrafVal.java
  18. 3 3
      utic-ptis-server/src/main/java/com/utic/ptis/server/dto/dwdb/ParamPatternEffectDay.java
  19. 4 4
      utic-ptis-server/src/main/java/com/utic/ptis/server/scheduler/LinkTrafPrcsScheduler.java
  20. 116 46
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkRepositoryService.java
  21. 5 5
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafCollectService.java
  22. 3 5
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafDeleteService.java
  23. 31 39
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafFusionService.java
  24. 40 35
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafMissingService.java
  25. 42 51
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafParamService.java
  26. 115 55
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPatternService.java
  27. 1 1
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPrcsTime.java
  28. 33 0
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPrepareService.java
  29. 10 7
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafSaveService.java
  30. 0 5
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/UticSqlSessionService.java
  31. 1 1
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafCollectWorker.java
  32. 69 21
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveCenterExtWorker.java
  33. 69 21
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveCenterWorker.java
  34. 67 61
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbCenterHistWorker.java
  35. 3 3
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbFusionLogWorker.java
  36. 115 21
      utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbMissingValueHistWorker.java
  37. 12 2
      utic-ptis-server/src/main/java/com/utic/ptis/server/utils/LogUtils.java
  38. 4 0
      utic-ptis-server/src/main/resources/application.yml
  39. 1 1
      utic-ptis-server/src/main/resources/logback-spring.xml
  40. 1 1
      utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/DwdbParamMapper.xml
  41. 1 1
      utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/DwdbTrafficMapper.xml
  42. 24 36
      utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/LinkPatternMapper.xml
  43. 60 5
      utic-ptis-server/src/test/java/com/utic/ptis/server/UticPtisServerApplicationTests.java

+ 87 - 4
utic-common/src/main/java/com/utic/common/utils/TimeUtils.java

@@ -131,10 +131,10 @@ public class TimeUtils {
     public static String getFiveMinString(Date paramDt) {
         Calendar cal = Calendar.getInstance();
         cal.setTime(paramDt);
-        cal.set(13, 0);
-        cal.set(14, 0);
-        int min = cal.get(12);
-        cal.add(12, -(min % 5));
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        int min = cal.get(Calendar.MINUTE);
+        cal.add(Calendar.MINUTE, -(min % 5));
         return (new SimpleDateFormat("yyyyMMddHHmmss")).format(cal.getTime());
     }
 
@@ -321,4 +321,87 @@ public class TimeUtils {
             return defaultSeconds;
         }
     }
+    public static boolean isQuarterHour(String dateTimeStr) {
+        // 날짜 형식 변환
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+        LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, formatter);
+
+        // 분을 15로 나누어서 나머지 확인
+        int minutes = dateTime.getMinute();
+        return minutes % 15 == 0; // 0, 15, 30, 45분이면 true 반환
+    }
+    public static String addMinutes(String dateTimeStr, int minutesToAdd) {
+        // 날짜 형식 변환
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+        LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, formatter);
+
+        // 15분 추가
+        LocalDateTime updatedDateTime = dateTime.plusMinutes(minutesToAdd);
+
+        // 다시 문자열로 변환
+        return updatedDateTime.format(formatter);
+    }
+    public static String roundToQuarterHour(String dateTimeStr) {
+        // 날짜 형식 변환
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+        LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, formatter);
+
+        // 현재 분을 가져옴
+        int minutes = dateTime.getMinute();
+
+        // 15분 단위로 반올림 (0, 15, 30, 45)
+        int roundedMinutes;
+        if (minutes == 0) {
+            roundedMinutes = 0;
+        } else if (minutes >= 1 && minutes <= 15) {
+            roundedMinutes = 15;
+        } else if (minutes >= 16 && minutes <= 30) {
+            roundedMinutes = 30;
+        } else if (minutes >= 31 && minutes <= 45) {
+            roundedMinutes = 45;
+        } else { // 45~59분 → 다음 시간의 0분으로 변경
+            roundedMinutes = 0;
+            dateTime = dateTime.plusHours(1);
+        }
+
+        // 새로운 분 설정
+        dateTime = dateTime.withMinute(roundedMinutes).withSecond(0);
+
+        // 다시 문자열로 변환하여 반환
+        return dateTime.format(formatter);
+    }
+
+    public static String addDays(String dateTimeStr, int days) {
+        // 날짜 형식 변환
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+        LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, formatter);
+
+        // 일(day) 추가 또는 빼기
+        LocalDateTime updatedDateTime = dateTime.plusDays(days);
+
+        // 다시 문자열로 변환
+        return updatedDateTime.format(formatter);
+    }
+
+
+//    public static String getQuarterHour(String dateTimeStr) {
+//        String prcsTime = TimeUtils.getFiveMinString(TimeUtils.stringToDate(dateTimeStr));
+//        Date paramDt = stringToDate(prcsTime);
+//        Calendar cal = Calendar.getInstance();
+//        cal.setTime(paramDt);
+//        cal.set(Calendar.SECOND, 0);
+//        cal.set(Calendar.MILLISECOND, 0);
+//        int min = cal.get(Calendar.MINUTE);
+//        int nam = min % 15;
+//        int calMin = 15 - nam;
+////        if (nam == 5) {
+////            cal.add(Calendar.MINUTE, 10);
+////        } else if (nam == 10) {
+////            cal.add(Calendar.MINUTE, 5);
+////        } else {
+////            return prcsTime;
+////        }
+//        cal.add(Calendar.MINUTE, calMin);
+//        return new SimpleDateFormat("yyyyMMddHHmmss").format(cal.getTime());
+//    }
 }

+ 0 - 2
utic-dwdb-server/src/main/java/com/utic/dwdb/server/dao/mapper/BatchDaoService.java

@@ -57,7 +57,6 @@ public abstract class BatchDaoService {
                 jobCnt++;
                 if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                     sqlSession.flushStatements();
-                    sqlSession.clearCache();
                 }
             }
         }
@@ -107,7 +106,6 @@ public abstract class BatchDaoService {
                 jobCnt++;
                 if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                     sqlSession.flushStatements();
-                    sqlSession.clearCache();
                 }
             }
             success = true;

+ 9 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/UticPtisServerApplication.java

@@ -54,6 +54,7 @@ public class UticPtisServerApplication implements CommandLineRunner, Application
         log.info("************************************************************************************");
 
         ApplicationConfig applicationConfig = SpringUtils.getBean(ApplicationConfig.class);
+        applicationConfig.setStartSchedule(false);
 
         ProcessStateService processStateService = SpringUtils.getBean(ProcessStateService.class);
         processStateService.processStart();
@@ -61,8 +62,11 @@ public class UticPtisServerApplication implements CommandLineRunner, Application
         LinkRepositoryService linkRepositoryService = SpringUtils.getBean(LinkRepositoryService.class);
         linkRepositoryService.processing();
 
+        LinkTrafPrepareService linkTrafPrepareService = SpringUtils.getBean(LinkTrafPrepareService.class);
+        linkTrafPrepareService.processing();
+
         LinkTrafPrcsController linkTrafPrcsController = SpringUtils.getBean(LinkTrafPrcsController.class);
-        linkTrafPrcsController.run();
+//        linkTrafPrcsController.run();
 
         applicationConfig.setStartSchedule(true);
 
@@ -79,8 +83,11 @@ public class UticPtisServerApplication implements CommandLineRunner, Application
 
             log.error("************************************************************************************");
             log.error("**    Application Terminated: {}", sdfDate.format(new Date()));
-            ProcessStateService processStateService = SpringUtils.getBean(ProcessStateService.class);
             try {
+                ApplicationConfig applicationConfig = SpringUtils.getBean(ApplicationConfig.class);
+                applicationConfig.setStartSchedule(false);
+
+                ProcessStateService processStateService = SpringUtils.getBean(ProcessStateService.class);
                 processStateService.processStop();
             }
             catch (Exception e) {

+ 24 - 0
utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafEtlpController.java

@@ -0,0 +1,24 @@
+package com.utic.ptis.server.controller;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StopWatch;
+
+@Slf4j
+@Controller
+@RequiredArgsConstructor
+public class LinkTrafEtlpController implements AbstractProcessController {
+
+    public void initialize() {
+    }
+
+    public void run() {
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start("LinkTrafPrcsPrepareController");
+        log.info("[PREPARE]                  LinkTrafPrcsPrepareController: START.");
+
+        stopWatch.stop();
+        log.info("[PREPARE]                  LinkTrafPrcsPrepareController: ..END. {} ms", stopWatch.getTotalTimeMillis());
+    }
+}

+ 23 - 30
utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafPrcsController.java

@@ -12,7 +12,6 @@ import org.springframework.util.StopWatch;
 @RequiredArgsConstructor
 public class LinkTrafPrcsController implements AbstractProcessController {
 
-    private final LinkTrafPrcsTime prcsTime;
     private final LinkTrafParamService trafParamService;
     private final LinkRepositoryService linkRepo;
     private final LinkTrafDeleteService trafDeleteService;
@@ -20,61 +19,49 @@ public class LinkTrafPrcsController implements AbstractProcessController {
     private final LinkTrafFusionService trafFusionService;
     private final LinkTrafMissingService trafMissingService;
     private final LinkTrafSaveService trafSaveService;
+    private final UticSqlSessionService sqlSessionService;
 
-    private String statTime;
-    private String fromTime;
-    private String toTime;
+    private final LinkTrafPrepareService linkTrafPrepareService;
 
+    private boolean isProcessing = false;
     public void initialize() {
-
-        String currTime = TimeUtils.getCurrentTimeString();
-        this.statTime = TimeUtils.getTime(TimeUtils.TYPE_PRCS_15MIN);
-        this.fromTime = this.statTime;
-        this.toTime = TimeUtils.getToTime(this.fromTime, TimeUtils.TYPE_PRCS_15MIN);
-
-        String funcName = String.format("%45s", "LinkTrafPrcsController.initialize");
-        log.info("[PRCS...] {}: ..05M, {}, {}, {}, {}", funcName, currTime, this.statTime, this.fromTime, this.toTime);
-
         /*
          * 가공에 사용되는 시각 정보를 초기화 한다.
          * 데이터 처리를 위해 현재 가공시각을 재설정한다.
          */
-        this.prcsTime.init();
+        String currTime = TimeUtils.getCurrentTimeString();
+        String prcsTime = TimeUtils.getFiveMinString(TimeUtils.stringToDate(currTime));
+        String patternTime = TimeUtils.roundToQuarterHour(prcsTime);
 
-        this.linkRepo.setPrcsTime(this.prcsTime.getCurrFiveMin());
+        this.linkRepo.setPrcsTime(prcsTime);
+        this.linkRepo.setPatternTime(patternTime);
 
         this.linkRepo.getFusionInfo().init();
-        this.linkRepo.getFusionInfo().setRegDate(this.prcsTime.getCurrFiveMin());
+        this.linkRepo.getFusionInfo().setRegDate(this.linkRepo.getPrcsTime());
         this.linkRepo.getFusionInfo().setPrcsType(this.trafParamService.getAnalysisType().getAnalysisType());
         this.linkRepo.getFusionInfo().setLinkCnt(this.linkRepo.getLink1Count());
 
-        log.info("[TIME...]Current/Current_5M/Current_5M_Prcs: {}/{}/{}",    this.prcsTime.getCurrTime(),      this.prcsTime.getCurrFiveMin(),     this.prcsTime.getPrcsFiveMin());
-        log.info("[TIME...]         Current_5M_Prcs/Start/End: {}/{}/{}",    this.prcsTime.getPrcsFiveMin(),   this.prcsTime.getPrcsFiveMinFrom(), this.prcsTime.getPrcsFiveMinTo());
-        log.info("[TIME...]      Current_5M_Prcs/Week/Quarter: {}/{}/{}/{}", this.prcsTime.getPrcsFiveMin(),   this.prcsTime.getPrcsDayWeek(),     this.prcsTime.getPrcsDayQuater(),      this.prcsTime.getPrcsDayWeekCd());
-        log.info("[TIME...]          15M:PrcsTM/Start/End/Run: {}/{}/{}/{}", this.prcsTime.getStat15MinTime(), this.prcsTime.getStat15MinFrom(),   this.prcsTime.getStat15MinTo(),        this.prcsTime.isStat15Min());
-        log.info("[TIME...]         Hour:PrcsTM/Start/End/Run: {}/{}/{}/{}", this.prcsTime.getStatHourTime(),  this.prcsTime.getStatHourFrom(),    this.prcsTime.getStatHourTo(),         this.prcsTime.isStatHour());
-        log.info("[TIME...]          Day:PrcsTM/Start/End/Run: {}/{}/{}/{}", this.prcsTime.getStatDayTime(),   this.prcsTime.getStatDayFrom(),     this.prcsTime.getStatDayTo(),          this.prcsTime.isStatDay());
-        log.info("[TIME...]        Month:PrcsTM/Start/End/Run: {}/{}/{}/{}", this.prcsTime.getStatMonTime(),   this.prcsTime.getStatMonFrom(),     this.prcsTime.getStatMonTo(),          this.prcsTime.isStatMon());
-        log.info("[TIME...]         Year:PrcsTM/Start/End/Run: {}/{}/{}/{}", this.prcsTime.getStatYearTime(),  this.prcsTime.getStatYearFrom(),    this.prcsTime.getStatYearTo(),         this.prcsTime.isStatYear());
+        log.info("[TIME...]      Current/PrcsTime/PatternTime: {}/{}/{}", currTime, this.linkRepo.getPrcsTime(), this.linkRepo.getPatternTime());
     }
 
     public void run() {
 
-        if (this.prcsTime.isProcessing()) {
-            log.error("Previous processing is not completed.");
+        log.info("[TRAFFIC] >>>>>>>>>>>>>>>>>>>>>>> 5분주기 작업 시작.");
+        if (this.isProcessing) {
+            log.error("[TRAFFIC] ======================= 5분주기 작업 시작. 실패: 이전주기 작업이 실행중입니다.");
         }
 
         StopWatch stopWatch = new StopWatch();
         stopWatch.start("LinkTrafPrcsController");
-        log.info("[TRAFFIC]                         LinkTrafPrcsController: START.");
 
         // 가공 시작
-        this.prcsTime.setProcessing(true);
+        this.isProcessing = true;
 
         // 가공처리 작업을 수행하기 위한 초기화 작업을 수행한다.
         initialize();
 
         // 0. 소통정보 저장할 테이블 삭제
+        this.sqlSessionService.processing();
         this.trafDeleteService.processing();
 
         // 1. 수집원별 링크 원시 교통정보 조회
@@ -91,9 +78,15 @@ public class LinkTrafPrcsController implements AbstractProcessController {
 
         // 5. 소통정보 저장
         this.trafSaveService.processing();
-        this.prcsTime.setProcessing(false);
+        this.sqlSessionService.complete();
+
+        // 7. 가공 완료
+        this.isProcessing = false;
+
+        this.linkTrafPrepareService.processing();
+
         stopWatch.stop();
-        log.info("[TRAFFIC]                         LinkTrafPrcsController: ..END. {} ms", stopWatch.getTotalTimeMillis());
+        log.info("[TRAFFIC] <<<<<<<<<<<<<<<<<<<<<<< 5분주기 작업 완료. {} ms.\n", stopWatch.getTotalTimeMillis());
 
     }
 }

+ 0 - 47
utic-ptis-server/src/main/java/com/utic/ptis/server/controller/LinkTrafPrcsPrepareController.java

@@ -1,47 +0,0 @@
-package com.utic.ptis.server.controller;
-
-import com.utic.ptis.server.service.LinkTrafParamService;
-import com.utic.ptis.server.service.LinkTrafPatternService;
-import com.utic.ptis.server.service.LinkTrafPrcsTime;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Controller;
-import org.springframework.util.StopWatch;
-
-@Slf4j
-@Controller
-@RequiredArgsConstructor
-public class LinkTrafPrcsPrepareController implements AbstractProcessController {
-
-    private final LinkTrafPrcsTime prcsTime;
-    private final LinkTrafParamService linkTrafParamService;
-    private final LinkTrafPatternService linkTrafPatternService;
-
-    public void initialize() {
-    }
-
-    public void run() {
-        StopWatch stopWatch = new StopWatch();
-        stopWatch.start("LinkTrafPrcsPrepareController");
-        log.info("[PREPARE]                  LinkTrafPrcsPrepareController: START.");
-
-        /*
-         * 가공에 사용되는 시각 정보를 초기화 한다.
-         * 기본정보를 미리 읽기위해 가공시간 설정
-         */
-        this.prcsTime.init();
-
-        /*
-         * 파라미터 정보 로딩
-         */
-        this.linkTrafParamService.processing();
-
-        /*
-         * 패턴정보 로딩
-         */
-        this.linkTrafPatternService.processing();
-
-        stopWatch.stop();
-        log.info("[PREPARE]                  LinkTrafPrcsPrepareController: ..END. {} ms", stopWatch.getTotalTimeMillis());
-    }
-}

+ 0 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/BatchDaoService.java

@@ -59,7 +59,6 @@ public abstract class BatchDaoService {
                 jobCnt++;
                 if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                     sqlSession.flushStatements();
-                    sqlSession.clearCache();
                 }
             }
         }
@@ -88,7 +87,6 @@ public abstract class BatchDaoService {
                 jobCnt++;
                 if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                     sqlSession.flushStatements();
-                    sqlSession.clearCache();
                 }
             }
         }

+ 2 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/DwdbParamMapper.java

@@ -1,7 +1,7 @@
 package com.utic.ptis.server.dao.mapper.dwdb;
 
 import com.utic.ptis.server.dto.dwdb.ParamAnalysisType;
-import com.utic.ptis.server.dto.dwdb.ParamEffectDays;
+import com.utic.ptis.server.dto.dwdb.ParamPatternEffectDay;
 import com.utic.ptis.server.dto.dwdb.ParamHoliday;
 import com.utic.ptis.server.dto.dwdb.ParamMissing;
 import org.apache.ibatis.annotations.Mapper;
@@ -14,7 +14,7 @@ public interface DwdbParamMapper {
 
     ParamAnalysisType findAnalysisType();
 
-    ParamEffectDays findEffectDays();
+    ParamPatternEffectDay findEffectDays();
 
     ParamMissing findMissing();
 

+ 2 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/DwdbTrafficMapper.java

@@ -1,6 +1,6 @@
 package com.utic.ptis.server.dao.mapper.dwdb;
 
-import com.utic.ptis.server.dto.LinkMissingValueHist;
+import com.utic.ptis.server.dto.LinkMissingValueHistDto;
 import com.utic.ptis.server.dto.LinkTrafCenterDto;
 import com.utic.ptis.server.dto.LinkTrafFusionInfo;
 import org.apache.ibatis.annotations.Mapper;
@@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Param;
 public interface DwdbTrafficMapper {
     int insertTrafficCenterHist(@Param("obj") LinkTrafCenterDto obj);
     int insertLinkFusionLog(@Param("obj") LinkTrafFusionInfo obj);
-    int insertLinkMissingValueHist(@Param("obj") LinkMissingValueHist obj);
+    int insertLinkMissingValueHist(@Param("obj") LinkMissingValueHistDto obj);
 }

+ 7 - 7
utic-ptis-server/src/main/java/com/utic/ptis/server/dao/mapper/dwdb/LinkPatternMapper.java

@@ -1,6 +1,6 @@
 package com.utic.ptis.server.dao.mapper.dwdb;
 
-import com.utic.ptis.server.dto.LinkCollectParam;
+import com.utic.ptis.server.dto.LinkPatternParam;
 import com.utic.ptis.server.dto.LinkPtrnVal;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -10,10 +10,10 @@ import java.util.List;
 @Mapper
 public interface LinkPatternMapper {
 
-    List<LinkPtrnVal> findLinkPatternHoliday15M(@Param("obj") LinkCollectParam obj);
-    List<LinkPtrnVal> findLinkPatternSun15M(@Param("obj") LinkCollectParam obj);
-    List<LinkPtrnVal> findLinkPatternMon15M(@Param("obj") LinkCollectParam obj);
-    List<LinkPtrnVal> findLinkPatternFri15M(@Param("obj") LinkCollectParam obj);
-    List<LinkPtrnVal> findLinkPatternSat15M(@Param("obj") LinkCollectParam obj);
-    List<LinkPtrnVal> findLinkPatternWeek15M(@Param("obj") LinkCollectParam obj);
+    List<LinkPtrnVal> findLinkPatternHoliday15M(@Param("obj") LinkPatternParam obj);
+    List<LinkPtrnVal> findLinkPatternSun15M(@Param("obj") LinkPatternParam obj);
+    List<LinkPtrnVal> findLinkPatternMon15M(@Param("obj") LinkPatternParam obj);
+    List<LinkPtrnVal> findLinkPatternFri15M(@Param("obj") LinkPatternParam obj);
+    List<LinkPtrnVal> findLinkPatternSat15M(@Param("obj") LinkPatternParam obj);
+    List<LinkPtrnVal> findLinkPatternWeek15M(@Param("obj") LinkPatternParam obj);
 }

+ 20 - 0
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/DbmsBatchJobResult.java

@@ -5,6 +5,8 @@ import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.List;
+
 @Data
 @Builder
 @NoArgsConstructor//(access = AccessLevel.PROTECTED)
@@ -21,4 +23,22 @@ public class DbmsBatchJobResult {
     private int link3;
     private int link4;
     private long elapsedTime;
+    private List<String>linkIds;
+
+    @Override
+    public String toString() {
+        return "DbmsBatchJobResult{" +
+                "jobIndex=" + jobIndex +
+                ", start=" + start +
+                ", end=" + end +
+                ", total=" + total +
+                ", target=" + target +
+                ", effects=" + effects +
+                ", link1=" + link1 +
+                ", link2=" + link2 +
+                ", link3=" + link3 +
+                ", link4=" + link4 +
+                ", elapsedTime=" + elapsedTime +
+                '}';
+    }
 }

+ 0 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkCollectParam.java

@@ -11,6 +11,4 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class LinkCollectParam {
     private String ansTime;
-    private String nowDateTime;
-    private Integer missingEffDays;
 }

+ 34 - 6
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkDto.java

@@ -25,6 +25,7 @@ public class LinkDto  implements Serializable {
 
     private String upLinkId;
     private String dnLinkId;
+    private String link4Id;
     private ArrayList<String> linkIds;
 
     private boolean prcsPtrnMissing;    // 패턴 결측 처리 여부(링크 레벨1 인 경우)
@@ -37,13 +38,20 @@ public class LinkDto  implements Serializable {
     private LinkTrafMiss missPsd;       // PSD 알고리즘 수행 값
     private LinkTrafMiss missKnn;       // k-NN 알고리즘 수행 값
 
-    public LinkTrafCenterDto getTrafficDto(String regDate) {
-        return this.trafFsn.toDto(this.linkId, this.linkLevel, regDate, missPsd, missKnn, 0);
+    private LinkTrafCenterDto trafCenter; // 소통정보 센터 전송 DTO
+
+//    public LinkTrafCenterDto getTrafCenter(String regDate) {
+//        return this.trafCenter;
+//        //return this.trafFsn.toDto(this.linkId, this.linkLevel, regDate, missPsd, missKnn, 0);
+//    }
+    public LinkTrafCenterDto getTrafCenterExt(String regDate) {
+        return this.trafExt.toDto(this.linkId, this.linkLevel, regDate, missPsd, missKnn, 0);
     }
 
     public void init() {
         this.upLinkId = "";
         this.dnLinkId = "";
+        this.link4Id = "";
         this.linkIds = new ArrayList<>();
         this.prcsPtrnMissing = false;
 
@@ -52,16 +60,36 @@ public class LinkDto  implements Serializable {
         this.trafExt = new LinkTrafVal();
         this.missPsd = new LinkTrafMiss();
         this.missKnn = new LinkTrafMiss();
+        this.trafCenter = new LinkTrafCenterDto(this.linkId, this.linkLevel);
     }
 
-    public void initTraf(boolean initPtrnTraf) {
-        if (initPtrnTraf) {
-            this.trafPtrn.init();
-        }
+    public void initTraf() {
         this.trafFsn.init();
         this.trafExt.init();
         this.missPsd.init();
         this.missKnn.init();
+        this.trafCenter.init();
+    }
+    public void initPtrn() {
+        this.trafPtrn.init();
+    }
+
+    public void makeCenterTraffic(String regDate) {
+        LinkTrafVal fsn = this.trafFsn;
+        this.trafCenter.setTrafValid(fsn.getState().isState());
+        this.trafCenter.setRegDate(regDate);
+        this.trafCenter.setLinkId(linkId);
+        this.trafCenter.setMissValueYn(fsn.getState().getMissValueYn());
+        this.trafCenter.setSpeed(fsn.getSpeed());
+        this.trafCenter.setTravelTime(fsn.getTravelTime());
+        this.trafCenter.setTrafficGrade("0" + fsn.getState().getTrafficGrade());
+        this.trafCenter.setIncidentId("");
+        this.trafCenter.setDataResType(fsn.getState().getDataResType());
+        this.trafCenter.setCenterId(fsn.getCenterId());
+        this.trafCenter.setPsdMissValueYn(this.missPsd.getMissValueYn());
+        this.trafCenter.setPsdSpeed(this.missPsd.getSpeed());
+        this.trafCenter.setKnnSpeed(this.missKnn.getSpeed());
+        this.trafCenter.setKnnCnt(0);
     }
 
     public int getTravelTime(int speed) {

+ 7 - 7
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkMissingValueHist.java → utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkMissingValueHistDto.java

@@ -5,7 +5,7 @@ import lombok.Data;
 import java.io.Serializable;
 
 @Data
-public class LinkMissingValueHist implements Serializable {
+public class LinkMissingValueHistDto implements Serializable {
     private static final long serialVersionUID = 1L;
 
     private String linkId;
@@ -26,13 +26,16 @@ public class LinkMissingValueHist implements Serializable {
     private int knnSpeed;
     private int knnCnt;
 
-    public LinkMissingValueHist() {
+    public LinkMissingValueHistDto(LinkDto link, String exeDate) {
+        this.linkId = link.getLinkId();
+        this.exeDate = exeDate;
+        this.l4LinkId = link.getLink4Id();
+        this.upLinkId = link.getUpLinkId();
+        this.dnLinkId = link.getDnLinkId();
         init();
     }
 
     public void init() {
-        this.linkId = "";
-        this.exeDate = "";
         this.l4LinkSpd = 0;
         this.upLinkSpd = 0;
         this.dnLinkSpd = 0;
@@ -42,9 +45,6 @@ public class LinkMissingValueHist implements Serializable {
         this.linkPatnSpd = 0;
         this.missingType = "";
         this.revisionSpd = 0;
-        this.l4LinkId = "";
-        this.upLinkId = "";
-        this.dnLinkId = "";
         this.psdSpeed = 0;
         this.knnSpeed = 0;
         this.knnCnt = 0;

+ 15 - 0
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkPatternParam.java

@@ -0,0 +1,15 @@
+package com.utic.ptis.server.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor//(access = AccessLevel.PROTECTED)
+@AllArgsConstructor
+public class LinkPatternParam {
+    private String patnTime;
+    private String logDate;
+}

+ 24 - 6
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkTrafCenterDto.java

@@ -1,15 +1,10 @@
 package com.utic.ptis.server.dto;
 
-import lombok.AllArgsConstructor;
-import lombok.Builder;
 import lombok.Data;
-import lombok.NoArgsConstructor;
 
 @Data
-@Builder
-@NoArgsConstructor//(access = AccessLevel.PROTECTED)
-@AllArgsConstructor
 public class LinkTrafCenterDto {
+    private boolean isTrafValid;
     private String linkId;
     private String missValueYn;
     private String regDate;
@@ -25,4 +20,27 @@ public class LinkTrafCenterDto {
     private int    psdSpeed;
     private int    knnSpeed;
     private int    knnCnt;
+
+    public LinkTrafCenterDto(String linkId, int linkLevel) {
+        this.linkLevel = linkLevel;
+        this.linkId = linkId;
+        init();
+    }
+
+    public void init() {
+        this.isTrafValid = false;
+        this.missValueYn = "N";
+        this.regDate = "";
+        this.speed = 0;
+        this.travelTime = 0;
+        this.trafficGrade = "00";
+        this.incidentId = "";
+        this.dataResType = "0";
+        this.centerId = "C00";
+
+        this.psdMissValueYn = "N";
+        this.psdSpeed = 0;
+        this.knnSpeed = 0;
+        this.knnCnt = 0;
+    }
 }

+ 14 - 16
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/LinkTrafVal.java

@@ -36,22 +36,20 @@ public class LinkTrafVal implements Serializable {
     }
 
     public LinkTrafCenterDto toDto(String linkId, int linkLevel, String regDate, LinkTrafMiss missPsd, LinkTrafMiss missKnn, int knnCnt) {
-        return LinkTrafCenterDto.builder()
-                .linkId(linkId)
-                .missValueYn(this.getState().getMissValueYn())
-                .regDate(regDate)
-                .linkLevel(linkLevel)
-                .speed(this.speed)
-                .travelTime(this.travelTime)
-                .trafficGrade("0" + this.getState().getTrafficGrade())
-                .incidentId("")
-                .dataResType(this.getState().getDataResType())
-                .centerId(this.centerId)
-                .psdMissValueYn(missPsd.getMissValueYn())
-                .psdSpeed(missPsd.getSpeed())
-                .knnSpeed(missKnn.getSpeed())
-                .knnCnt(knnCnt)
-                .build();
+        LinkTrafCenterDto dto = new LinkTrafCenterDto(linkId, linkLevel);
+        dto.setMissValueYn(this.getState().getMissValueYn());
+        dto.setRegDate(regDate);
+        dto.setSpeed(this.speed);
+        dto.setTravelTime(this.travelTime);
+        dto.setTrafficGrade("0" + this.getState().getTrafficGrade());
+        dto.setIncidentId("");
+        dto.setDataResType(this.getState().getDataResType());
+        dto.setCenterId(this.centerId);
+        dto.setPsdMissValueYn(missPsd.getMissValueYn());
+        dto.setPsdSpeed(missPsd.getSpeed());
+        dto.setKnnSpeed(missKnn.getSpeed());
+        dto.setKnnCnt(knnCnt);
+        return dto;
     }
 
     public void setTraffic(LinkCollectDto traffic) {

+ 3 - 3
utic-ptis-server/src/main/java/com/utic/ptis/server/dto/dwdb/ParamEffectDays.java → utic-ptis-server/src/main/java/com/utic/ptis/server/dto/dwdb/ParamPatternEffectDay.java

@@ -11,12 +11,12 @@ import java.io.Serializable;
 @Builder
 @NoArgsConstructor//(access = AccessLevel.PROTECTED)
 @AllArgsConstructor
-public class ParamEffectDays implements Serializable {
+public class ParamPatternEffectDay implements Serializable {
     private static final long serialVersionUID = 1L;
 
     private Integer effectDays;    // 효과일수(기본 365일)
 
-    public void setParam(ParamEffectDays paramEffectDays) {
-        this.effectDays = paramEffectDays.getEffectDays();
+    public void setParam(ParamPatternEffectDay paramPatternEffectDay) {
+        this.effectDays = paramPatternEffectDay.getEffectDays();
     }
 }

+ 4 - 4
utic-ptis-server/src/main/java/com/utic/ptis/server/scheduler/LinkTrafPrcsScheduler.java

@@ -4,7 +4,7 @@ import com.utic.common.annotation.ScheduleElapsed;
 import com.utic.ptis.server.config.ApplicationConfig;
 import com.utic.ptis.server.controller.AbstractProcessController;
 import com.utic.ptis.server.controller.LinkTrafPrcsController;
-import com.utic.ptis.server.controller.LinkTrafPrcsPrepareController;
+import com.utic.ptis.server.controller.LinkTrafEtlpController;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.EnableScheduling;
@@ -18,7 +18,7 @@ import org.springframework.stereotype.Component;
 public class LinkTrafPrcsScheduler {
 
     private final ApplicationConfig applicationConfig;
-    private final LinkTrafPrcsPrepareController linkTrafPrcsPrepareController;
+    private final LinkTrafEtlpController linkTrafEtlpController;
     private final LinkTrafPrcsController linkTrafPrcsController;
 
     private void runJob(AbstractProcessController job, String jobName) {
@@ -31,10 +31,10 @@ public class LinkTrafPrcsScheduler {
     }
 
     @ScheduleElapsed
-    @Scheduled(cron = "5 3/5 * * * *")  // 5분주기 - 1분전 작업 실행
+    @Scheduled(cron = "5 4/5 * * * *")  // 5분주기 - 1분전 작업 실행
     public void scheduleLinkTrafPrepareProcess() {
         if (this.applicationConfig.isStartSchedule()) {
-            runJob(this.linkTrafPrcsPrepareController, "Prepare Link Traffic Processing");
+            runJob(this.linkTrafEtlpController, "Link Traffic Etlp Processing");
         }
     }
 

+ 116 - 46
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkRepositoryService.java

@@ -4,17 +4,16 @@ import com.utic.common.utils.Elapsed;
 import com.utic.ptis.server.config.ApplicationConfig;
 import com.utic.ptis.server.dao.mapper.dwdb.DwdbParamMapper;
 import com.utic.ptis.server.dao.mapper.utic.LinkMapper;
-import com.utic.ptis.server.dto.LinkCountDto;
-import com.utic.ptis.server.dto.LinkDto;
-import com.utic.ptis.server.dto.LinkTrafFusionInfo;
-import com.utic.ptis.server.dto.LogicalLinkDto;
+import com.utic.ptis.server.dto.*;
 import com.utic.ptis.server.repository.ApplicationRepository;
 import com.utic.ptis.server.utils.LogUtils;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -29,24 +28,24 @@ public class LinkRepositoryService implements AbstractProcessService {
 
     private final DwdbParamMapper dwdbParamMapper;
     private final LinkMapper linkMapper;
-    private final LinkTrafParamService linkTrafParamService;
 
     private final ConcurrentHashMap<String, LinkDto> linkMap = new ConcurrentHashMap<>();
     private final LinkTrafFusionInfo fusionInfo = new LinkTrafFusionInfo();
-    private volatile String[] linkArr = null;
-    private volatile String[] link1Arr = null;
+    private List<String> linkLists = null;
+    private List<String> link1Lists = null;
     private int link1Count = 0;
     private int link2Count = 0;
     private int link3Count = 0;
     private int link4Count = 0;
-    private String prcsTime;
+
+    @Setter
+    private String prcsTime = "20000101000000";
+    @Setter
+    private String patternTime = "20000101000000";
 
     public LinkDto getLink(String linkId) {
         return this.linkMap.get(linkId);
     }
-    public void setPrcsTime(String prcsTime) {
-        this.prcsTime = prcsTime;
-    }
 
     private boolean initializeLinkCount() {
         boolean result = true;
@@ -63,14 +62,14 @@ public class LinkRepositoryService implements AbstractProcessService {
 
         int totalLinkCount = this.link1Count + this.link2Count + this.link3Count + this.link4Count;
         if (this.link1Count > 0) {
-            this.link1Arr = new String[this.link1Count];
+            this.link1Lists = new ArrayList<>(this.link1Count);
         }
         else {
             log.error("[INIT...] totalLinkCount is zero.");
             result = false;
         }
         if (totalLinkCount > 0) {
-            this.linkArr = new String[totalLinkCount];
+            this.linkLists = new ArrayList<>(totalLinkCount);
         }
         else {
             log.error("[INIT...] totalLinkCount is zero.");
@@ -95,7 +94,8 @@ public class LinkRepositoryService implements AbstractProcessService {
             link.init();
 
             if (link.getLinkLevel() == 1) {
-                this.link1Arr[link1++] = link.getLinkId();
+                this.link1Lists.add(link.getLinkId());
+                link1++;
             } else if (link.getLinkLevel() == 2) {
                 link2++;
             } else if (link.getLinkLevel() == 3) {
@@ -103,7 +103,8 @@ public class LinkRepositoryService implements AbstractProcessService {
             } else if (link.getLinkLevel() == 4) {
                 link4++;
             }
-            this.linkArr[linkCnt++] = link.getLinkId();
+            linkCnt++;
+            this.linkLists.add(link.getLinkId());
             this.linkMap.put(link.getLinkId(), link);
         }
         log.info("[INIT...] findLinkAll:  (MEM) {}, LV1({}), LV2({}), LV3({}), LV4({}).",
@@ -126,11 +127,11 @@ public class LinkRepositoryService implements AbstractProcessService {
 
             tmpElapsed.reset();
             int calCnt = 0;
-            for (LogicalLinkDto grp : links) {
-                String logicalLinkId = grp.getLogicalLinkId();
-                LinkDto link = this.linkMap.get(logicalLinkId);
-                if (link != null) {
-                    link.setLinkIds(grp.getLinkIds());
+            for (LogicalLinkDto logicalLinkDto : links) {
+                String logicalLinkId = logicalLinkDto.getLogicalLinkId();
+                LinkDto logicalLink = this.linkMap.get(logicalLinkId);
+                if (logicalLink != null) {
+                    logicalLink.setLinkIds(logicalLinkDto.getLinkIds());
                 }
                 else {
                     log.error("[INIT...] findLogicalLinkAll: LogicalLink({}), Level({}) is null.", logicalLinkId, linkLevel);
@@ -138,32 +139,35 @@ public class LinkRepositoryService implements AbstractProcessService {
                     continue;
                 }
 
-                int linkCount = grp.getLinkIds().size();
+                int linkCount = logicalLinkDto.getLinkIds().size();
                 if (linkCount <= 1) {
                     continue;   // 1 개의 구간으로 구성된 로지컬링크.
                 }
 
                 // 레벨 4일경우에만 해도 됌.
-                for (int ii = 0; ii < grp.getLinkIds().size(); ii++) {
-                    String linkId = grp.getLinkIds().get(ii);
-                    LinkDto grpLink = this.linkMap.get(linkId);
-                    if (grpLink == null) {
-                        log.error("[INIT...] findLogicalLinkAll: LogicalLink({}), Level({}), Link({}) is null.", logicalLinkId, linkLevel, linkId);
-                        continue;
-                    }
+                if (linkLevel == 4) {
+                    for (int ii = 0; ii < logicalLinkDto.getLinkIds().size(); ii++) {
+                        String linkId = logicalLinkDto.getLinkIds().get(ii);
+                        LinkDto link = this.linkMap.get(linkId);
+                        if (link == null) {
+                            log.error("[INIT...] findLogicalLinkAll: LogicalLink({}), Level({}), Link({}) is null.", logicalLinkId, linkLevel, linkId);
+                            continue;
+                        }
 
-                    if (ii == 0) {
-                        // 첫번째
-                        grpLink.setUpLinkId(grp.getLinkIds().get(ii + 1));
-                    } else if (ii == linkCount - 1) {
-                        // 마지막
-                        grpLink.setDnLinkId(grp.getLinkIds().get(ii - 1));
-                    } else {
-                        // 중간
-                        grpLink.setUpLinkId(grp.getLinkIds().get(ii + 1));
-                        grpLink.setDnLinkId(grp.getLinkIds().get(ii - 1));
+                        link.setLink4Id(logicalLink.getLinkId());
+                        if (ii == 0) {
+                            // 첫번째
+                            link.setUpLinkId(logicalLinkDto.getLinkIds().get(ii + 1));
+                        } else if (ii == linkCount - 1) {
+                            // 마지막
+                            link.setDnLinkId(logicalLinkDto.getLinkIds().get(ii - 1));
+                        } else {
+                            // 중간
+                            link.setUpLinkId(logicalLinkDto.getLinkIds().get(ii + 1));
+                            link.setDnLinkId(logicalLinkDto.getLinkIds().get(ii - 1));
+                        }
+                        calCnt++;
                     }
-                    calCnt++;
                 }
             }
             log.info("[INIT...] findLogicalLinkAll: Level({}) LOGICAL SUB LINK: {} EA. {}",
@@ -202,8 +206,6 @@ public class LinkRepositoryService implements AbstractProcessService {
         log.info("[INIT...] LinkRepositoryService.processing: start.");
         Elapsed elapsed = new Elapsed();
 
-        this.linkTrafParamService.processing();
-
         initializeLinkCount();          // 링크 레벨별 갯수 조회
         initializeLink();               // 링크 레벨별 정보 조회
         initializeLogicalLink();        // 로지컬링크 정보 조회
@@ -213,12 +215,80 @@ public class LinkRepositoryService implements AbstractProcessService {
         return 0;
     }
 
-    public void initLinkTraf(boolean initPtrnTraf) {
-        log.info("[INIT...] LinkRepositoryService.initLinkTraf: start.");
-        Elapsed elapsed = new Elapsed();
+    public void initLinkTraf() {
+        this.linkMap.forEach((linkId, link) -> {
+            link.initTraf();
+        });
+    }
+
+    public void initLinkPtrn() {
         this.linkMap.forEach((linkId, link) -> {
-            link.initTraf(initPtrnTraf);
+            link.initPtrn();
         });
-        log.info("[INIT...] LinkRepositoryService.initLinkTraf: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+    }
+
+    public LinkMissingValueHistDto getMissingValueHist(LinkDto link, String exeDate) {
+        if (!link.isPrcsPtrnMissing()) {
+            return null;
+        }
+        if (link.getTrafFsn().getState().getCrtDataType() == LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL) {
+            return null;
+        }
+        if (link.getTrafFsn().getState().getMissValueYn().equals("O")) {
+            // 운영자가 입력한 소통정보이면 결측자료로 처리하지 않는다.(20131113)
+            return null;
+        }
+
+        LinkMissingValueHistDto valueHist = new LinkMissingValueHistDto(link, exeDate);
+        if (link.getTrafFsn().getState().isState()) {
+            // 결측값
+            valueHist.setMissingType(link.getTrafFsn().getState().getMissValueYn());
+            valueHist.setRevisionSpd(link.getTrafFsn().getSpeed());
+        }
+        if (link.getTrafPtrn().getState().isState()) {
+            // 패턴값
+            valueHist.setRevisionSpd(link.getTrafPtrn().getSpeed());
+        }
+        LinkDto upLink = this.linkMap.get(link.getUpLinkId());
+        if (upLink != null) {
+            // 상류부 링크
+            if (upLink.getTrafFsn().getState().isState() && upLink.getTrafFsn().getState().getCrtDataType() == LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL) {
+                valueHist.setUpLinkSpd(upLink.getTrafFsn().getSpeed());
+            }
+            if (upLink.getTrafPtrn().getState().isState()) {
+                valueHist.setUpPatnSpd(upLink.getTrafPtrn().getSpeed());
+            }
+        }
+        LinkDto dnLink = this.linkMap.get(link.getDnLinkId());
+        if (dnLink != null) {
+            // 상류부 링크
+            if (dnLink.getTrafFsn().getState().isState() && dnLink.getTrafFsn().getState().getCrtDataType() == LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL) {
+                valueHist.setDnLinkSpd(dnLink.getTrafFsn().getSpeed());
+            }
+            if (dnLink.getTrafPtrn().getState().isState()) {
+                valueHist.setDnPatnSpd(dnLink.getTrafPtrn().getSpeed());
+            }
+        }
+        LinkDto grpLink = this.linkMap.get(link.getLink4Id());
+        if (grpLink != null) {
+            // 레벨4 링크
+            if (grpLink.getTrafFsn().getState().isState() && grpLink.getTrafFsn().getState().getCrtDataType() == LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL) {
+                valueHist.setL4LinkSpd(grpLink.getTrafFsn().getSpeed());
+            }
+            if (grpLink.getTrafPtrn().getState().isState()) {
+                valueHist.setL4PatnSpd(grpLink.getTrafPtrn().getSpeed());
+            }
+        }
+        valueHist.setPsdSpeed(link.getMissPsd().getSpeed());
+        valueHist.setKnnSpeed(link.getMissKnn().getSpeed());
+        valueHist.setKnnCnt(0);
+        return valueHist;
+    }
+
+    public void makeCenterTraffic() {
+        this.linkMap.values().parallelStream()
+                .forEach(link -> {
+                    link.makeCenterTraffic(this.prcsTime);
+                });
     }
 }

+ 5 - 5
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafCollectService.java

@@ -5,6 +5,7 @@ import com.utic.ptis.server.dto.LinkCollectParam;
 import com.utic.ptis.server.dto.LinkCollectResultDto;
 import com.utic.ptis.server.dto.LinkCollectSetupDto;
 import com.utic.ptis.server.service.worker.LinkTrafCollectWorker;
+import com.utic.ptis.server.utils.LogUtils;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
@@ -23,7 +24,6 @@ import java.util.concurrent.TimeUnit;
 @Service
 public class LinkTrafCollectService implements AbstractProcessService {
 
-    private final LinkTrafPrcsTime prcsTime;
     private final LinkRepositoryService linkRepo;
     private final LinkTrafCollectSetupService collectSetupService;
 
@@ -41,7 +41,7 @@ public class LinkTrafCollectService implements AbstractProcessService {
     }
 
     public int processing() {
-        log.info("[COLLECT] LinkTrafCollectService.processing: start.");
+        log.info("[COLLECT]****** {}", LogUtils.elapsedLog("수집 교통정보 조회 시작"));
         Elapsed elapsed = new Elapsed();
         init();
 
@@ -52,7 +52,7 @@ public class LinkTrafCollectService implements AbstractProcessService {
         }
 
         LinkCollectParam collectParam = LinkCollectParam.builder()
-                .ansTime(this.prcsTime.getCurrFiveMin())
+                .ansTime(this.linkRepo.getPrcsTime())
                 .build();
 
         ExecutorService executorService = Executors.newFixedThreadPool(clctSystCnt);
@@ -78,9 +78,9 @@ public class LinkTrafCollectService implements AbstractProcessService {
             if (collect != null) {
                 systStup.setClctNum(collect.getLists().size());
             }
-            log.info("[COLLECT] LinkTrafCollectService.processing: [{}] {}, [{}] EA.", clctSystCode, systStup.getClctSystNm(), systStup.getClctNum());
+            log.info("[COLLECT] ..... {}: {} EA.", LogUtils.elapsedLog(clctSystCode + systStup.getClctSystNm()), systStup.getClctNum());
         }
-        log.info("[COLLECT] LinkTrafCollectService.processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        log.info("[COLLECT]****** {}", LogUtils.elapsedLog("수집 교통정보 조회 완료", elapsed.milliSeconds()));
         return this.mapData.size();
     }
 

+ 3 - 5
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafDeleteService.java

@@ -45,8 +45,7 @@ public class LinkTrafDeleteService implements AbstractProcessService {
     }
 
     public int processing() {
-        log.info("[DELETE.] LinkTrafDeleteService.processing: start.");
-        Elapsed elapsed = new Elapsed();
+        log.info("[DELETE.] (DEL) {}", LogUtils.elapsedLog("교통정보 삭제 시작"));
 
         if (this.executorService.isShutdown() || this.executorService.isTerminated()) {
             this.executorService = Executors.newFixedThreadPool(2);
@@ -57,7 +56,6 @@ public class LinkTrafDeleteService implements AbstractProcessService {
             result.setElapsedTime(0);
             this.executorService.execute(new LinkTrafDeleteWorker(deleteTable, result, this.mapper));
         });
-        log.info("[DELETE.] LinkTrafDeleteService.processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return 2;
     }
 
@@ -77,10 +75,10 @@ public class LinkTrafDeleteService implements AbstractProcessService {
         for (Map.Entry<String, DbmsJobResult> entry : this.mapData.entrySet()) {
             DbmsJobResult result = entry.getValue();
             elapsedTime = Math.max(elapsedTime, result.getElapsedTime());
-            log.info("[DELETE.] LinkTrafDeleteService.waitForComplete:  (DEL) {}", LogUtils.elapsedLog(result.getTableName(), result.getEffects(), result.getElapsedTime()));
+            log.info("[DELETE.] (DEL) {}", LogUtils.elapsedLog(result.getTableName(), result.getEffects(), result.getElapsedTime()));
         }
 
-        log.info("[DELETE.] LinkTrafDeleteService.waitForComplete: end. {} ms.", elapsedTime);
+        log.info("[DELETE.] (DEL) {}", LogUtils.elapsedLog("교통정보 삭제 완료", elapsedTime));
     }
 
 }

+ 31 - 39
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafFusionService.java

@@ -7,6 +7,7 @@ import com.utic.ptis.server.dto.LinkDto;
 import com.utic.ptis.server.dto.dwdb.ParamAnalysisType;
 import com.utic.ptis.server.dto.utic.TrafficGrade;
 import com.utic.ptis.server.dto.utic.TrafficWeight;
+import com.utic.ptis.server.utils.LogUtils;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -37,11 +38,9 @@ public class LinkTrafFusionService implements AbstractProcessService {
     private LinkCollectResultDto collectMOCT;
 
     private void initialize() {
-        log.info("[FUSION.] LinkTrafFusionService.initialize: start.");
-        Elapsed elapsed = new Elapsed();
 
         // 0. 링크 소통정보를 초기화 한다.
-        this.linkRepo.initLinkTraf(true);
+        this.linkRepo.initLinkTraf();
 
         // 1. 수집된 소통정보를 객체로 초기화 한다.
         this.collectOPER = Optional.ofNullable(this.collectService.get(LinkTrafCollectSetupService.OPER))
@@ -65,11 +64,10 @@ public class LinkTrafFusionService implements AbstractProcessService {
         this.linkRepo.getFusionInfo().setColMoctCnt(this.collectMOCT.getLists().size());
         this.linkRepo.getFusionInfo().setColGpsCnt(0);  // GPS 수집정보는 없음
 
-        log.info("[FUSION.] LinkTrafFusionService.initialize: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
     }
 
     public int processing() {
-        log.info("[FUSION.] LinkTrafFusionService.processing: start.");
+        log.info("[FUSION.]****** {}", LogUtils.elapsedLog("교통정보 가공 시작"));
         Elapsed elapsed = new Elapsed();
 
         // 0. 퓨전 초기화
@@ -94,12 +92,12 @@ public class LinkTrafFusionService implements AbstractProcessService {
         // 4. 소통정보 보정(속도, 통행시간 계산)
         trafficCorrect();
 
-        log.info("[FUSION.] LinkTrafFusionService.processing: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        log.info("[FUSION.]****** {}", LogUtils.elapsedLog("교통정보 가공 종료", elapsed.milliSeconds()));
         return 0;
     }
 
     private int trafficCorrect() {
-        log.info("[FUSION.] LinkTrafFusionService.trafficCorrect: start.");
+//        log.info("[FUSION.] LinkTrafFusionService.trafficCorrect: start.");
         Elapsed elapsed = new Elapsed();
 
         AtomicInteger nCalCnt = new AtomicInteger();
@@ -117,7 +115,7 @@ public class LinkTrafFusionService implements AbstractProcessService {
             );
 
         this.linkRepo.getFusionInfo().setFltSpdCnt(nCalCnt.get());
-        log.info("[FUSION.] LinkTrafFusionService.trafficCorrect: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[FUSION.] LinkTrafFusionService.trafficCorrect: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
@@ -138,39 +136,32 @@ public class LinkTrafFusionService implements AbstractProcessService {
         log.info("[FUSION.] LinkTrafFusionService.priorityFusion: start.");
         Elapsed elapsed = new Elapsed();
 
-        AtomicInteger nCalCnt = new AtomicInteger();
-        this.collectUTIS.getLists().parallelStream()
-                .forEach(clctTraf -> {
-                    if (fusionTraffic(clctTraf, LinkTrafCollectSetupService.UTIS)) {
-                        nCalCnt.incrementAndGet();
-                    }
-                });
-        this.collectPRIO.getLists().parallelStream()
-                .forEach(clctTraf -> {
-                    if (fusionTraffic(clctTraf, LinkTrafCollectSetupService.PRIO)) {
-                        nCalCnt.incrementAndGet();
-                    }
-                });
-        this.collectPRIOETC.getLists().parallelStream()
-                .forEach(clctTraf -> {
-                    if (fusionTraffic(clctTraf, LinkTrafCollectSetupService.PRIOETC)) {
-                        nCalCnt.incrementAndGet();
-                    }
-                });
-        this.collectDONGBU.getLists().parallelStream()
-                .forEach(clctTraf -> {
-                    if (fusionTraffic(clctTraf, LinkTrafCollectSetupService.DONGBU)) {
-                        nCalCnt.incrementAndGet();
-                    }
-                });
+        String[] priorityCollectCD = {
+                LinkTrafCollectSetupService.UTIS,
+                LinkTrafCollectSetupService.PRIO,
+                LinkTrafCollectSetupService.PRIOETC,
+                LinkTrafCollectSetupService.DONGBU
+        };
 
+        AtomicInteger nCalCnt = new AtomicInteger();
+        for (String clctSystCd : priorityCollectCD) {
+            LinkCollectResultDto collectResultDto = Optional.ofNullable(this.collectService.get(clctSystCd))
+                    .orElseGet(() -> LinkCollectResultDto.builder().clctSystCd(clctSystCd).lists(new ArrayList<>()).build());
+
+            collectResultDto.getLists().parallelStream()
+                    .forEach(clctTraf -> {
+                        if (fusionTraffic(clctTraf, clctSystCd)) {
+                            nCalCnt.incrementAndGet();
+                        }
+                    });
+        }
         this.linkRepo.getFusionInfo().setFsnPriCnt(nCalCnt.get());
         log.info("[FUSION.] LinkTrafFusionService.priorityFusion: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int weightFusion() {
-        log.info("[FUSION.] LinkTrafFusionService.weightFusion: start.");
+//        log.info("[FUSION.] LinkTrafFusionService.weightFusion: start.");
         Elapsed elapsed = new Elapsed();
 
         Map<String, LinkCollectDto> utisMap = this.collectUTIS.getLists().stream()
@@ -247,7 +238,7 @@ public class LinkTrafFusionService implements AbstractProcessService {
                 });
 
         this.linkRepo.getFusionInfo().setFsnWgtCnt(nCalCnt.get());
-        log.info("[FUSION.] LinkTrafFusionService.weightFusion: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[FUSION.] LinkTrafFusionService.weightFusion: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
@@ -265,9 +256,10 @@ public class LinkTrafFusionService implements AbstractProcessService {
     }
 
     private int externalFusion() {
-        log.info("[FUSION.] LinkTrafFusionService.externalFusion: start.");
+//        log.info("[FUSION.] LinkTrafFusionService.externalFusion: start.");
         Elapsed elapsed = new Elapsed();
 
+        // 동부 NTS 정보를 제외한 소통정보 생성
         AtomicInteger nCalCnt = new AtomicInteger();
         this.collectUTIS.getLists().parallelStream()
                 .forEach(clctTraf -> {
@@ -288,12 +280,12 @@ public class LinkTrafFusionService implements AbstractProcessService {
                     }
                 });
 
-        log.info("[FUSION.] LinkTrafFusionService.externalFusion: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[FUSION.] LinkTrafFusionService.externalFusion: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int operatorFusion() {
-        log.info("[FUSION.] LinkTrafFusionService.operatorFusion: start.");
+//        log.info("[FUSION.] LinkTrafFusionService.operatorFusion: start.");
         Elapsed elapsed = new Elapsed();
         int nCalCnt = 0;
         for (LinkCollectDto dto : this.collectOPER.getLists()) {
@@ -307,7 +299,7 @@ public class LinkTrafFusionService implements AbstractProcessService {
             nCalCnt++;
         }
         this.linkRepo.getFusionInfo().setFsnOprCnt(nCalCnt);
-        log.info("[FUSION.] LinkTrafFusionService.operatorFusion: ..end. {} EA. {}", nCalCnt, Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[FUSION.] LinkTrafFusionService.operatorFusion: ..end. {} EA. {}", nCalCnt, Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt;
     }
 

+ 40 - 35
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafMissingService.java

@@ -6,6 +6,7 @@ import com.utic.ptis.server.dto.LinkCollectResultDto;
 import com.utic.ptis.server.dto.LinkDto;
 import com.utic.ptis.server.dto.LinkTrafState;
 import com.utic.ptis.server.dto.utic.TrafficGrade;
+import com.utic.ptis.server.utils.LogUtils;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -27,7 +28,7 @@ public class LinkTrafMissingService implements AbstractProcessService {
     private final LinkTrafPatternService patternService;
 
     public int processing() {
-        log.info("[MISSING] LinkTrafMissingService.processing: start.");
+        log.info("[MISSING]****** {}", LogUtils.elapsedLog("교통정보 결측 시작"));
         Elapsed elapsed = new Elapsed();
 
         // 모든 결측 알고리즘에 대해 결측 처리를 수행하고 
@@ -60,12 +61,12 @@ public class LinkTrafMissingService implements AbstractProcessService {
             groupLinkTrafficCreate(ii, "P");
         }
 
-        log.info("[MISSING] LinkTrafMissingService.processing: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        log.info("[MISSING]****** {}", LogUtils.elapsedLog("교통정보 결측 종료", elapsed.milliSeconds()));
         return 0;
     }
 
     private int missingLinkMoct() {
-        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: start.");
         Elapsed elapsed = new Elapsed();
 
         // 결측처리 방식: 국토부 민간소통정보를 이용하여 결측
@@ -95,12 +96,12 @@ public class LinkTrafMissingService implements AbstractProcessService {
         }
 
         this.linkRepo.getFusionInfo().setMissMoctCnt(nCalCnt);
-        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: ..end. {} EA. {}", nCalCnt, Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: ..end. {} EA. {}", nCalCnt, Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt;
     }
 
     private int missingLinkExternal() {
-        log.info("[MISSING] LinkTrafMissingService.missingLinkExternal: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkExternal: start.");
         Elapsed elapsed = new Elapsed();
 
         // 결측처리 방식: 구간의 현재 패턴정보를 이용
@@ -128,48 +129,52 @@ public class LinkTrafMissingService implements AbstractProcessService {
                 }
             );
 
-        log.info("[MISSING] LinkTrafMissingService.missingLinkExternal: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkExternal: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int missingLinkPattern() {
-        log.info("[MISSING] LinkTrafMissingService.missingLinkPattern: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkPattern: start.");
         Elapsed elapsed = new Elapsed();
 
         this.linkRepo.getFusionInfo().setColPtnCnt(this.patternService.getPatternCount());
 
-        // 결측처리 방식: 구간의 현재 패턴정보를 이용
+        // 결측처리 방식: 구간의 현재 패턴정보를 이용, DB에 패턴정보 결측 처리를 수행하도록 설정된 링크에 대해서만 처리한다.
         AtomicInteger nCalCnt = new AtomicInteger();
         this.linkRepo.getLinkMap().values().parallelStream()
                 .filter(link -> link.getLinkLevel() == 1)
                 .forEach(link -> {
-                            // 구간의 퓨전소통정보가 존재하면 처리하지 않음
-                            if (link.getTrafFsn().getState().isState()) {
-                                return;
-                            }
-                            // 구간의 패턴소통정보가 존재하지 않으면 처리하지 못함
-                            if (!link.getTrafPtrn().getState().isState()) {
-                                return;
-                            }
+                    if (!link.isPrcsPtrnMissing()) {
+                        // 패턴 결측 처리를 수행하도록 설정된 링크에 대해서만 결측 처리
+                        return;
+                    }
+                    // 구간의 퓨전소통정보가 존재하면 처리하지 않음
+                    if (link.getTrafFsn().getState().isState()) {
+                        return;
+                    }
+                    // 구간의 패턴소통정보가 존재하지 않으면 처리하지 못함
+                    if (!link.getTrafPtrn().getState().isState()) {
+                        return;
+                    }
 
-                            if (link.getTrafPtrn().getSpeed() > 0) {
-                                TrafficGrade grade = Optional.ofNullable(this.trafParamService.getTrafGradeMap().get(link.getLinkId()))
-                                        .orElseGet(() -> TrafficGrade.builder().roadRank("999").minSpeed(30).maxSpeed(49).build());
-                                link.getTrafFsn().getState().setCrtDataType(LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_MISSING);
-                                link.getTrafFsn().setTraffic("C00", link.getTrafPtrn().getSpeed(), "T", "P");
-                                link.getTrafExt().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed());
-                                nCalCnt.incrementAndGet();
-                            }
-                        }
-                );
+                    if (link.getTrafPtrn().getSpeed() > 0) {
+                        TrafficGrade grade = Optional.ofNullable(this.trafParamService.getTrafGradeMap().get(link.getLinkId()))
+                                .orElseGet(() -> TrafficGrade.builder().roadRank("999").minSpeed(30).maxSpeed(49).build());
+                        link.getTrafFsn().getState().setCrtDataType(LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_MISSING);
+                        link.getTrafFsn().setTraffic("C00", link.getTrafPtrn().getSpeed(), "T", "P");
+                        link.getTrafExt().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed());
+                        nCalCnt.incrementAndGet();
+                    }
+                }
+            );
 
         this.linkRepo.getFusionInfo().setMissPtnCnt(nCalCnt.get());
-        log.info("[MISSING] LinkTrafMissingService.missingLinkPattern: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkPattern: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int missingLinkCorrect() {
-        log.info("[MISSING] LinkTrafMissingService.missingLinkCorrect: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkCorrect: start.");
         Elapsed elapsed = new Elapsed();
 
         // 결측처리 방식: 우선순위, KNN(사용하지 않음)
@@ -199,12 +204,12 @@ public class LinkTrafMissingService implements AbstractProcessService {
         this.linkRepo.getFusionInfo().setMissPsdCnt(nCalCnt.get());
         this.linkRepo.getFusionInfo().setMissKnnCnt(0); // knn 알고리즘 수행하지 않음
 
-        log.info("[MISSING] LinkTrafMissingService.missingLinkCorrect: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkCorrect: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int missingLinkPsd() {
-        log.info("[MISSING] LinkTrafMissingService.missingLinkPsd: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkPsd: start.");
         Elapsed elapsed = new Elapsed();
 
         /* PSD 알고리즘 결측정보 처리
@@ -282,12 +287,12 @@ public class LinkTrafMissingService implements AbstractProcessService {
                 }
             );
 
-        log.info("[MISSING] LinkTrafMissingService.missingLinkPsd: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingLinkPsd: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int groupLinkTrafficCreate(int linkLevel, String dataResType) {
-        log.info("[MISSING] LinkTrafMissingService.groupLinkTrafficCreate[Level:{}]: start.", linkLevel);
+//        log.info("[MISSING] LinkTrafMissingService.groupLinkTrafficCreate[Level:{}]: start.", linkLevel);
         Elapsed elapsed = new Elapsed();
         AtomicInteger nCalCnt = new AtomicInteger();
 
@@ -344,12 +349,12 @@ public class LinkTrafMissingService implements AbstractProcessService {
                 }
             );
 
-        log.info("[MISSING] LinkTrafMissingService.groupLinkTrafficCreate[Level:{}]: ..end. {} EA. {}", linkLevel, nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.groupLinkTrafficCreate[Level:{}]: ..end. {} EA. {}", linkLevel, nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 
     private int missingGroupPsd() {
-        log.info("[MISSING] LinkTrafMissingService.missingGroupPsd: start.");
+//        log.info("[MISSING] LinkTrafMissingService.missingGroupPsd: start.");
         Elapsed elapsed = new Elapsed();
         AtomicInteger nCalCnt = new AtomicInteger();
 
@@ -397,7 +402,7 @@ public class LinkTrafMissingService implements AbstractProcessService {
             }
         );
 
-        log.info("[MISSING] LinkTrafMissingService.missingGroupPsd: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
+//        log.info("[MISSING] LinkTrafMissingService.missingGroupPsd: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return nCalCnt.get();
     }
 

+ 42 - 51
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafParamService.java

@@ -4,11 +4,10 @@ import com.utic.common.utils.Elapsed;
 import com.utic.ptis.server.dao.mapper.dwdb.DwdbParamMapper;
 import com.utic.ptis.server.dao.mapper.utic.UticParamMapper;
 import com.utic.ptis.server.dto.dwdb.ParamAnalysisType;
-import com.utic.ptis.server.dto.dwdb.ParamEffectDays;
-import com.utic.ptis.server.dto.dwdb.ParamHoliday;
 import com.utic.ptis.server.dto.dwdb.ParamMissing;
 import com.utic.ptis.server.dto.utic.TrafficGrade;
 import com.utic.ptis.server.dto.utic.TrafficWeight;
+import com.utic.ptis.server.utils.LogUtils;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -30,10 +29,6 @@ public class LinkTrafParamService implements AbstractProcessService {
             .analysisType(ParamAnalysisType.ANALYSIS_TYPE_PRIORITY)
             .build();
 
-    private final ParamEffectDays effectDays = ParamEffectDays.builder()
-            .effectDays(365)
-            .build();
-
     private final ParamMissing missing = ParamMissing.builder()
             .usePst(true)
             .useKnn(true)
@@ -42,72 +37,68 @@ public class LinkTrafParamService implements AbstractProcessService {
             .missPri(true)
             .build();
 
-    private final ParamHoliday holiday = ParamHoliday.builder()
-            .wDay(0)
-            .hCnt(0)
-            .build();
-
     private final ConcurrentHashMap<String, TrafficGrade> trafGradeMap = new ConcurrentHashMap<>();
     private final ConcurrentHashMap<String, TrafficWeight> trafWeightMap = new ConcurrentHashMap<>();
 
     public int processing() {
-        log.info("[PARAM..] processing: start.");
-        Elapsed elapsed = new Elapsed();
+//        log.info("[PARAM..] processing: start.");
+//        Elapsed elapsed = new Elapsed();
 
-        try {
-            ParamAnalysisType analysisType1 = this.dwdbParamMapper.findAnalysisType();
-            this.analysisType.setParam(analysisType1);
-            log.info("{}", this.analysisType);
-        } catch (Exception e) {
-            log.error("findAnalysisType: {}", e.getMessage());
-        }
+        loadingTrafficGrade();
+        loadingTrafficWeight();
+        loadingTrafficMissing();
+        loadingTrafficAnalysisType();
+
+//        log.info("[PARAM..] processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        return 0;
+    }
 
+    public void loadingTrafficAnalysisType() {
+        Elapsed elapsed = new Elapsed();
         try {
-            ParamEffectDays effectDays1 = this.dwdbParamMapper.findEffectDays();
-            this.effectDays.setParam(effectDays1);
-            log.info("{}", this.effectDays);
+            ParamAnalysisType analysisType = this.dwdbParamMapper.findAnalysisType();
+            this.analysisType.setParam(analysisType);
+            log.info("[PARAM..] (SEL) {} [({})가공방식(0:우선순위,1:가중치)]",
+                    LogUtils.elapsedLog("가공파라미터", 1, elapsed.milliSeconds()),
+                    this.analysisType.getAnalysisType());
         } catch (Exception e) {
-            log.error("findEffectDays: {}", e.getMessage());
+            log.error("[PARAM..] findAnalysisType: Exception: {}", e.getMessage());
         }
-
+    }
+    public void loadingTrafficMissing() {
+        Elapsed elapsed = new Elapsed();
         try {
-            ParamMissing missing1 = this.dwdbParamMapper.findMissing();
-            this.missing.setParam(missing1);
-            log.info("{}", this.missing);
+            ParamMissing missing = this.dwdbParamMapper.findMissing();
+            this.missing.setParam(missing);
+            log.info("[PARAM..] (SEL) {} [PST({}), Pattern({}), 우선순위({})]",
+                    LogUtils.elapsedLog("결측파라미터", 1, elapsed.milliSeconds()),
+                    this.missing.isUsePst(), this.missing.isUsePtn(), this.missing.isMissPri());
         } catch (Exception e) {
-            log.error("findMissing: {}", e.getMessage());
+            log.error("[PARAM..] findMissing: Exception: {}", e.getMessage());
         }
-
+    }
+    public void loadingTrafficWeight() {
+        Elapsed elapsed = new Elapsed();
         try {
-            ParamHoliday holiday1 = this.dwdbParamMapper.findHoliday("20250429000000");
-            this.holiday.setParam(holiday1);
-            log.info("{}", this.holiday);
+            List<TrafficWeight> trafficWeights = this.uticParamMapper.findTrafficWeight();
+            for (TrafficWeight trafficWeight : trafficWeights) {
+                this.trafWeightMap.put(trafficWeight.getWeightCode(), trafficWeight);
+            }
+            log.info("[PARAM..] (SEL) {}", LogUtils.elapsedLog("가중치파라미터", trafficWeights.size(), elapsed.milliSeconds()));
         } catch (Exception e) {
-            log.error("findHoliday: {}", e.getMessage());
+            log.error("[PARAM..] findTrafficWeight: Exception: {}", e.getMessage());
         }
-
+    }
+    public void loadingTrafficGrade() {
+        Elapsed elapsed = new Elapsed();
         try {
             List<TrafficGrade> trafficGrades = this.uticParamMapper.findTrafficGrade();
             for (TrafficGrade trafficGrade : trafficGrades) {
                 this.trafGradeMap.put(trafficGrade.getRoadRank(), trafficGrade);
             }
-            log.info("{}", this.trafGradeMap);
-        } catch (Exception e) {
-            log.error("findTrafficGrade: {}", e.getMessage());
-        }
-
-        try {
-            List<TrafficWeight> trafficWeights = this.uticParamMapper.findTrafficWeight();
-            for (TrafficWeight trafficWeight : trafficWeights) {
-                this.trafWeightMap.put(trafficWeight.getWeightCode(), trafficWeight);
-            }
-            log.info("{}", this.trafGradeMap);
+            log.info("[PARAM..] (SEL) {}", LogUtils.elapsedLog("소통등급(TRAFFICGRADE)", trafficGrades.size(), elapsed.milliSeconds()));
         } catch (Exception e) {
-            log.error("findTrafficWeight: {}", e.getMessage());
+            log.error("[PARAM..] findTrafficGrade: Exception: {}", e.getMessage());
         }
-
-        log.info("[PARAM..] processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
-        return 0;
     }
-
 }

+ 115 - 55
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPatternService.java

@@ -1,20 +1,19 @@
 package com.utic.ptis.server.service;
 
 import com.utic.common.utils.Elapsed;
+import com.utic.common.utils.TimeUtils;
 import com.utic.ptis.server.dao.mapper.dwdb.DwdbParamMapper;
-import com.utic.ptis.server.dao.mapper.utic.UticParamMapper;
-import com.utic.ptis.server.dto.dwdb.ParamAnalysisType;
-import com.utic.ptis.server.dto.dwdb.ParamEffectDays;
+import com.utic.ptis.server.dao.mapper.dwdb.LinkPatternMapper;
+import com.utic.ptis.server.dto.*;
 import com.utic.ptis.server.dto.dwdb.ParamHoliday;
-import com.utic.ptis.server.dto.dwdb.ParamMissing;
-import com.utic.ptis.server.dto.utic.TrafficGrade;
+import com.utic.ptis.server.dto.dwdb.ParamPatternEffectDay;
+import com.utic.ptis.server.utils.LogUtils;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
 
 @Slf4j
 @Getter
@@ -22,81 +21,142 @@ import java.util.concurrent.ConcurrentHashMap;
 @Service
 public class LinkTrafPatternService implements AbstractProcessService {
 
+    private final LinkRepositoryService linkRepo;
     private final DwdbParamMapper dwdbParamMapper;
-    private final UticParamMapper uticParamMapper;
+    private final LinkPatternMapper patternMapper;
 
-    private final ParamAnalysisType analysisType = ParamAnalysisType.builder()
-            .analysisType(ParamAnalysisType.ANALYSIS_TYPE_PRIORITY)
-            .build();
-
-    private final ParamEffectDays effectDays = ParamEffectDays.builder()
+    private final ParamPatternEffectDay patternEffectDay = ParamPatternEffectDay.builder()
             .effectDays(365)
             .build();
 
-    private final ParamMissing missing = ParamMissing.builder()
-            .usePst(true)
-            .useKnn(true)
-            .usePtn(true)
-            .extKnn(true)
-            .missPri(true)
-            .build();
-
     private final ParamHoliday holiday = ParamHoliday.builder()
             .wDay(0)
             .hCnt(0)
             .build();
 
-    private final ConcurrentHashMap<String, TrafficGrade> trafGradeMap = new ConcurrentHashMap<>();
-
     private int patternCount = 0;
+    private String prcsTime = "20000101000000";
+    private String patternTime = "20000101000000";
+
+    private boolean initialize() {
+        String currTime = TimeUtils.getCurrentTimeString();
+        String nextTime = TimeUtils.addMinutes(currTime, 5);
+        this.prcsTime = TimeUtils.getFiveMinString(TimeUtils.stringToDate(nextTime));
+        String patternTime = TimeUtils.roundToQuarterHour(this.prcsTime);
+
+        log.info("[PATTERN] currTime[{}], nextTime[{}], prcsTime[{}], patternTime[{}]/[{}].", currTime, nextTime, this.prcsTime, patternTime, this.patternTime);
+
+        if (patternTime.equals(this.patternTime)) {
+            return false;
+        }
+        this.patternTime = patternTime;
+        return true;
+    }
 
     public int processing() {
-        log.info("[PATTERN] processing: start.");
-        Elapsed elapsed = new Elapsed();
+//        log.info("[PATTERN] processing: start.");
+//        Elapsed elapsed = new Elapsed();
 
-        try {
-            ParamAnalysisType analysisType1 = this.dwdbParamMapper.findAnalysisType();
-            this.analysisType.setParam(analysisType1);
-            log.info("{}", this.analysisType);
-        } catch (Exception e) {
-            log.error("findAnalysisType: {}", e.getMessage());
+        if (initialize()) {
+
+            loadingPatternParam();
+
+            this.linkRepo.initLinkPtrn();
+
+            loadingPatternSpeed();
         }
+//        log.info("[PATTERN] processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        return 0;
+    }
 
-        try {
-            ParamEffectDays effectDays1 = this.dwdbParamMapper.findEffectDays();
-            this.effectDays.setParam(effectDays1);
-            log.info("{}", this.effectDays);
-        } catch (Exception e) {
-            log.error("findEffectDays: {}", e.getMessage());
+    public void loadingPatternSpeed() {
+        log.info("[PATTERN] ..... {}: [{}][{}]", LogUtils.elapsedLog("패턴정보 조회 시작"), this.prcsTime, this.patternTime);
+        Elapsed elapsed = new Elapsed();
+
+        String logDate = TimeUtils.addDays(this.patternTime, -this.patternEffectDay.getEffectDays());
+        String patnTime = this.patternTime.substring(8, 12);
+
+        List<LinkPtrnVal> result = null;
+        LinkPatternParam param = LinkPatternParam.builder()
+                .logDate(logDate)
+                .patnTime(patnTime)
+                .build();
+
+        String logTable;
+        if (this.holiday.getHCnt() > 0) {
+            logTable = "(휴일)PATN_15MIN_HOLIDAY";
+            result = this.patternMapper.findLinkPatternHoliday15M(param);
         }
+        else {
+            switch(this.holiday.getWDay()) {
+                case 1: // 일요일 패턴
+                    logTable = "(일요일)PATN_15MIN_SUN";
+                    result = this.patternMapper.findLinkPatternSun15M(param);
+                    break;
+                case 2: // 월요일 패턴
+                    logTable = "(월요일)PATN_15MIN_MON";
+                    result = this.patternMapper.findLinkPatternMon15M(param);
+                    break;
+                case 6: // 금요일 패턴
+                    logTable = "(금요일)PATN_15MIN_FRI";
+                    result = this.patternMapper.findLinkPatternFri15M(param);
+                    break;
+                case 7: // 토요일 패턴
+                    logTable = "(토요일)PATN_15MIN_SAT";
+                    result = this.patternMapper.findLinkPatternSat15M(param);
+                    break;
+                default: // 평일 패턴(3,4,5)
+                    logTable = "(평일)PATN_15MIN_WEEK";
+                    result = this.patternMapper.findLinkPatternWeek15M(param);
+                    break;
+            }
+        }
+        this.patternCount = setLinkPatternSpeed(result);
+        log.info("[PATTERN] (SEL) {} [레벨1: {} EA, 레벨4: {} EA]",
+                LogUtils.elapsedLog(logTable, result.size(), elapsed.milliSeconds()), this.patternCount, result.size()-this.patternCount);
 
-        try {
-            ParamMissing missing1 = this.dwdbParamMapper.findMissing();
-            this.missing.setParam(missing1);
-            log.info("{}", this.missing);
-        } catch (Exception e) {
-            log.error("findMissing: {}", e.getMessage());
+        log.info("[PATTERN] ..... {}", LogUtils.elapsedLog("패턴정보 조회 완료", result.size(), elapsed.milliSeconds()));
+    }
+
+    private int setLinkPatternSpeed(List<LinkPtrnVal> result) {
+        int link1Count = 0;
+        for (LinkPtrnVal ptrnVal : result) {
+            LinkDto link = this.linkRepo.getLinkMap().get(ptrnVal.getLinkId());
+            if (link == null) {
+//                log.error("[PATTERN] setLinkPatternSpeed: LinkId[{}] not found.", ptrnVal.getLinkId());
+                continue;
+            }
+            link.getTrafPtrn().getState().setState(true);
+            link.getTrafPtrn().getState().setCrtDataType(LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL);
+            link.getTrafPtrn().setSpeed(ptrnVal.getSpeed());
+            if (link.getLinkLevel() == 1) {
+                link1Count++;
+            }
         }
+        return link1Count;
+    }
 
+    public void loadingPatternParam() {
+        Elapsed elapsed = new Elapsed();
         try {
-            ParamHoliday holiday1 = this.dwdbParamMapper.findHoliday("20250429000000");
-            this.holiday.setParam(holiday1);
-            log.info("{}", this.holiday);
+            ParamHoliday holiday = this.dwdbParamMapper.findHoliday(this.patternTime);
+            this.holiday.setParam(holiday);
+            log.info("[PATTERN] (SEL) {} [휴일유무({}), 요일({})]",
+                    LogUtils.elapsedLog("패턴 결측파라미터", 1, elapsed.milliSeconds()),
+                    this.holiday.getHCnt(), this.holiday.getWDay());
         } catch (Exception e) {
-            log.error("findHoliday: {}", e.getMessage());
+            log.error("[PATTERN] findHoliday: Exception: {}", e.getMessage());
         }
 
+        elapsed.reset();
         try {
-            List<TrafficGrade> trafficGrades = this.uticParamMapper.findTrafficGrade();
-            for (TrafficGrade trafficGrade : trafficGrades) {
-                this.trafGradeMap.put(trafficGrade.getRoadRank(), trafficGrade);
-            }
-            log.info("{}", this.trafGradeMap);
+            ParamPatternEffectDay effectDays1 = this.dwdbParamMapper.findEffectDays();
+            this.patternEffectDay.setParam(effectDays1);
+            log.info("[PATTERN] (SEL) {} [패턴유효일({})]",
+                    LogUtils.elapsedLog("패턴 결측파라미터", 1, elapsed.milliSeconds()),
+                    this.patternEffectDay.getEffectDays());
         } catch (Exception e) {
-            log.error("findTrafficGrade: {}", e.getMessage());
+            log.error("[PATTERN] findEffectDays: Exception: {}", e.getMessage());
         }
-        log.info("[PATTERN] processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
-        return 0;
     }
-
 }

+ 1 - 1
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPrcsTime.java

@@ -243,7 +243,7 @@ public class LinkTrafPrcsTime {
 		int sec   = cal.get(Calendar.SECOND);
 
 		String strCurrTime = String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
-		log.info("[TIME...] TrafficProcessingTime.init: {}", strCurrTime);
+		log.info("[TIME...]        TrafficProcessingTime.init: {}", strCurrTime);
 
 		cal.setTime(convertString2Date(this.prcsFiveMin));		/* 요일, 사사분기는 가공시각을 기준으로 계산 */
 		this.prcsDayWeek   = cal.get(Calendar.DAY_OF_WEEK);		/* DAY_OF_WEEK 리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다. */

+ 33 - 0
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafPrepareService.java

@@ -0,0 +1,33 @@
+package com.utic.ptis.server.service;
+
+import com.utic.common.utils.Elapsed;
+import com.utic.common.utils.TimeUtils;
+import com.utic.ptis.server.utils.LogUtils;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Data
+@ToString
+@RequiredArgsConstructor
+@Service
+public class LinkTrafPrepareService implements AbstractProcessService {
+
+    private final LinkTrafParamService linkTrafParamService;
+    private final LinkTrafPatternService linkTrafPatternService;
+
+    public int processing() {
+        log.info("[PREPARE]****** {}: [{}]", LogUtils.elapsedLog("가공 기초정보 로딩 시작"), TimeUtils.getCurrentTimeString());
+        Elapsed elapsed = new Elapsed();
+
+        this.linkTrafPatternService.processing();
+        this.linkTrafParamService.processing();
+
+        log.info("[PREPARE]****** {}", LogUtils.elapsedLog("가공 초기정보 로딩 완료", elapsed.milliSeconds()));
+        return 0;
+    }
+
+}

+ 10 - 7
utic-ptis-server/src/main/java/com/utic/ptis/server/service/LinkTrafSaveService.java

@@ -36,7 +36,6 @@ public class LinkTrafSaveService implements AbstractProcessService {
     private final UticSqlSessionService uticSqlSessionService;
     private final UticTrafficMapper uticMapper;
     private final DwdbTrafficMapper dwdbMapper;
-    private final LinkTrafPrcsTime prcsTime;
     private final LinkRepositoryService linkRepositoryService;
 
     private ConcurrentHashMap<String, DbmsJobResult> mapData = new ConcurrentHashMap<>();
@@ -67,11 +66,15 @@ public class LinkTrafSaveService implements AbstractProcessService {
                 .filter(link -> link.getTrafFsn().getSpeed() == 0)
                 .count();
         this.linkRepo.getFusionInfo().setZeroSpdCnt((int)count);
+
+        // 모든 링크에 대해 센터 소통정보 생성
+        this.linkRepo.makeCenterTraffic();
+
         return (int)count;
     }
 
     public int processing() {
-        log.info("[SAVE...] LinkTrafSaveService.processing: start.");
+        log.info("[SAVE...]****** {}", LogUtils.elapsedLog("교통정보 저장 시작"));
         Elapsed elapsed = new Elapsed();
 
         final int THREAD_POOL_SIZE = 5;     // 작업 스레드 개수 설정
@@ -81,10 +84,10 @@ public class LinkTrafSaveService implements AbstractProcessService {
         initialize();
 
         ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
-        executorService.execute(new LinkTrafSaveCenterWorker(this.linkRepo, this.mapData.get(TABLE_TRAFFIC_CENTER), this.uticSqlSessionService.getTrafficSqlSession(), this.prcsTime, this.uticMapper));
-        executorService.execute(new LinkTrafSaveCenterExtWorker(this.linkRepo, this.mapData.get(TABLE_TRAFFIC_CENTER_EXT), this.uticSqlSessionService.getTrafficExtSqlSession(), this.prcsTime, this.uticMapper));
+        executorService.execute(new LinkTrafSaveCenterWorker(this.linkRepo, this.mapData.get(TABLE_TRAFFIC_CENTER), this.uticSqlSessionService.getTrafficSqlSession()));
+        executorService.execute(new LinkTrafSaveCenterExtWorker(this.linkRepo, this.mapData.get(TABLE_TRAFFIC_CENTER_EXT), this.uticSqlSessionService.getTrafficExtSqlSession()));
         executorService.execute(new LinkTrafSaveDwdbCenterHistWorker(this.linkRepo, this.mapData.get(TABLE_TRAFFIC_CENTER_HIST)));
-        executorService.execute(new LinkTrafSaveDwdbMissingValueHistWorker(this.linkRepo, this.mapData.get(TABLE_LINK_MISSING_VALUE_HIST), this.prcsTime, this.dwdbMapper));
+        executorService.execute(new LinkTrafSaveDwdbMissingValueHistWorker(this.linkRepo, this.mapData.get(TABLE_LINK_MISSING_VALUE_HIST)));
         executorService.execute(new LinkTrafSaveDwdbFusionLogWorker(this.linkRepo, this.mapData.get(TABLE_LINK_FUSION_LOG), this.dwdbMapper));
 
         try {
@@ -102,10 +105,10 @@ public class LinkTrafSaveService implements AbstractProcessService {
         for (Map.Entry<String, DbmsJobResult> entry : this.mapData.entrySet()) {
             DbmsJobResult result = entry.getValue();
             elapsedTime = Math.max(elapsedTime, result.getElapsedTime());
-            log.info("[SAVE...] LinkTrafSaveService.processing:  (SAV) {}", LogUtils.elapsedLog(result.getTableName(), result.getEffects(), result.getElapsedTime()));
+            log.info("[SAVE...] (SAV) {}", LogUtils.elapsedLog(result.getTableName(), result.getEffects(), result.getElapsedTime()));
         }
 
-        log.info("[SAVE...] LinkTrafSaveService.processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
+        log.info("[SAVE...]****** {}", LogUtils.elapsedLog("교통정보 저장 시작", elapsed.milliSeconds()));
         return 0;
     }
 

+ 0 - 5
utic-ptis-server/src/main/java/com/utic/ptis/server/service/UticSqlSessionService.java

@@ -1,6 +1,5 @@
 package com.utic.ptis.server.service;
 
-import com.utic.common.utils.Elapsed;
 import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
@@ -39,11 +38,7 @@ public class UticSqlSessionService implements AbstractProcessService {
     }
 
     public int processing() {
-        log.info("[COLLECT] UticSqlSessionService.processing: start.");
-        Elapsed elapsed = new Elapsed();
-
         initialize();
-        log.info("[DELETE.] UticSqlSessionService.processing: end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds()));
         return 0;
     }
 

+ 1 - 1
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafCollectWorker.java

@@ -111,7 +111,7 @@ public class LinkTrafCollectWorker implements Runnable {
             this.mapData.put(this.clctSystCd, LinkCollectResultDto.builder().clctSystCd(this.clctSystCd).lists(new ArrayList<>()).build());
         }
         stopWatch.stop();
-        log.info("[COLLECT] LinkTrafCollectWorker.run:  (SEL) {}", LogUtils.elapsedLog(jobType, resultCount, stopWatch.getTotalTimeMillis()));
+        log.info("[COLLECT] (SEL) {}", LogUtils.elapsedLog(jobType, resultCount, stopWatch.getTotalTimeMillis()));
     }
 
 }

+ 69 - 21
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveCenterExtWorker.java

@@ -2,14 +2,16 @@ package com.utic.ptis.server.service.worker;
 
 import com.utic.ptis.server.dao.mapper.utic.UticTrafficMapper;
 import com.utic.ptis.server.dto.DbmsJobResult;
+import com.utic.ptis.server.dto.LinkTrafCenterDto;
 import com.utic.ptis.server.service.LinkRepositoryService;
-import com.utic.ptis.server.service.LinkTrafPrcsTime;
 import com.utic.ptis.server.utils.LogUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.SqlSession;
 import org.springframework.util.StopWatch;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 @Slf4j
 @RequiredArgsConstructor
 public class LinkTrafSaveCenterExtWorker implements Runnable {
@@ -17,36 +19,82 @@ public class LinkTrafSaveCenterExtWorker implements Runnable {
     private final LinkRepositoryService linkRepo;
     private final DbmsJobResult dbmsJobResult;
     private final SqlSession sqlSession;
-    private final LinkTrafPrcsTime prcsTime;
-    private final UticTrafficMapper mapper;
 
     @Override
     public void run() {
         String jobTable = this.dbmsJobResult.getTableName();
         StopWatch stopWatch = new StopWatch();
         stopWatch.start(jobTable);
-        int resultCount = 0;
-//        try {
-//            Thread.sleep(10);
-//
-//            if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenter();
-//            }
-//            else if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER_EXT.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenterExt();
-//            }
-//        }
-//        catch (InterruptedException e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: InterruptedException, [{}], {}.", this.jobTable, e.getMessage());
-//        }
-//        catch (Exception e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: Exception, [{}], {}.", this.jobTable, e.getMessage());
-//        }
 
+        UticTrafficMapper mapper = this.sqlSession.getMapper(UticTrafficMapper.class);
+
+        int[] linkResult = { 0, 0, 0, 0 };
+        try {
+            for (int ii = 0; ii < 4; ii++) {
+                linkResult[ii] = processBatch(ii+1, mapper, jobTable);
+                sqlSession.flushStatements();
+            }
+            sqlSession.commit();
+        } catch (Exception e) {
+            log.error("[SAVE...] LinkTrafSaveCenterExtWorker.run: Exception, [{}], {}.", jobTable, e.getMessage());
+        }
+
+        int resultCount = linkResult[0] + linkResult[1] + linkResult[2] + linkResult[3];
         stopWatch.stop();
         this.dbmsJobResult.setEffects(resultCount);
         this.dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveCenterExtWorker.run:  (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
+
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("소통정보(TRAFFIC_CENTER_EXT)", resultCount, stopWatch.getTotalTimeMillis()));
+    }
+
+    private int processBatch(int linkLevel, UticTrafficMapper mapper, String jobTable) {
+        final String mapperName = "insertTrafficCenterExt";
+        final int maxBatchSize = linkRepo.getConfig().getDbmsBatchSize();
+
+        AtomicInteger total = new AtomicInteger();
+        AtomicInteger missing = new AtomicInteger();
+        AtomicInteger zeroSpeed = new AtomicInteger();
+        AtomicInteger fusion = new AtomicInteger();
+        AtomicInteger jobCnt = new AtomicInteger();
+
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start(mapperName + linkLevel);
+
+        this.linkRepo.getLinkMap().values().stream()
+                .filter(link -> link.getLinkLevel() == linkLevel)
+                .forEach(link -> {
+                    total.getAndIncrement();
+
+                    if (link.getTrafExt().getState().isState()) {
+                        missing.getAndIncrement();
+                        return;
+                    }
+                    if (link.getTrafExt().getSpeed() == 0) {
+                        zeroSpeed.getAndIncrement();
+                        return;
+                    }
+
+                    fusion.getAndIncrement();
+                    LinkTrafCenterDto trafDto = link.getTrafCenterExt(this.linkRepo.getPrcsTime());
+                    try {
+                        mapper.insertTrafficCenterExt(trafDto);
+                        jobCnt.getAndIncrement();
+
+                        if (jobCnt.get() % maxBatchSize == 0) {
+                            sqlSession.flushStatements();
+                        }
+                    } catch (Exception e) {
+                        log.error("[SAVE...] LinkTrafSaveCenterExtWorker.processBatch: LinkLevel({}), jobCnt({}), Exception, [{}], {}.",
+                                linkLevel, jobCnt.get(), trafDto, e.getMessage());
+                    }
+                });
+
+        stopWatch.stop();
+        String msg = String.format("레벨%d 소통정보(TRAFFIC_CENTER_EXT)", linkLevel);
+        log.info("[SAVE...] (INS) {}, T/F/M/Z({}/{}/{}/{})",
+                LogUtils.elapsedLog(msg, jobCnt.get(), stopWatch.getTotalTimeMillis()),
+                total.get(), missing.get(), zeroSpeed.get(), fusion.get());
+        return jobCnt.get();
     }
 
 }

+ 69 - 21
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveCenterWorker.java

@@ -2,14 +2,16 @@ package com.utic.ptis.server.service.worker;
 
 import com.utic.ptis.server.dao.mapper.utic.UticTrafficMapper;
 import com.utic.ptis.server.dto.DbmsJobResult;
+import com.utic.ptis.server.dto.LinkTrafCenterDto;
 import com.utic.ptis.server.service.LinkRepositoryService;
-import com.utic.ptis.server.service.LinkTrafPrcsTime;
 import com.utic.ptis.server.utils.LogUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.session.SqlSession;
 import org.springframework.util.StopWatch;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 @Slf4j
 @RequiredArgsConstructor
 public class LinkTrafSaveCenterWorker implements Runnable {
@@ -17,36 +19,82 @@ public class LinkTrafSaveCenterWorker implements Runnable {
     private final LinkRepositoryService linkRepo;
     private final DbmsJobResult dbmsJobResult;
     private final SqlSession sqlSession;
-    private final LinkTrafPrcsTime prcsTime;
-    private final UticTrafficMapper mapper;
 
     @Override
     public void run() {
         String jobTable = this.dbmsJobResult.getTableName();
         StopWatch stopWatch = new StopWatch();
         stopWatch.start(jobTable);
-        int resultCount = 0;
-//        try {
-//            Thread.sleep(10);
-//
-//            if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenter();
-//            }
-//            else if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER_EXT.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenterExt();
-//            }
-//        }
-//        catch (InterruptedException e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: InterruptedException, [{}], {}.", this.jobTable, e.getMessage());
-//        }
-//        catch (Exception e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: Exception, [{}], {}.", this.jobTable, e.getMessage());
-//        }
 
+        UticTrafficMapper mapper = this.sqlSession.getMapper(UticTrafficMapper.class);
+
+        int[] linkResult = { 0, 0, 0, 0 };
+        try {
+            for (int ii = 0; ii < 4; ii++) {
+                linkResult[ii] = processBatch(ii+1, mapper, jobTable);
+                sqlSession.flushStatements();
+            }
+            sqlSession.commit();
+        } catch (Exception e) {
+            log.error("[SAVE...] LinkTrafSaveCenterWorker.run: Exception, [{}], {}.", jobTable, e.getMessage());
+        }
+
+        int resultCount = linkResult[0] + linkResult[1] + linkResult[2] + linkResult[3];
         stopWatch.stop();
         this.dbmsJobResult.setEffects(resultCount);
         this.dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveCenterWorker.run:  (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
+
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("소통정보(TRAFFIC_CENTER)", resultCount, stopWatch.getTotalTimeMillis()));
+    }
+
+    private int processBatch(int linkLevel, UticTrafficMapper mapper, String jobTable) {
+        final String mapperName = "insertTrafficCenter";
+        final int maxBatchSize = linkRepo.getConfig().getDbmsBatchSize();
+
+        AtomicInteger total = new AtomicInteger();
+        AtomicInteger missing = new AtomicInteger();
+        AtomicInteger zeroSpeed = new AtomicInteger();
+        AtomicInteger fusion = new AtomicInteger();
+        AtomicInteger jobCnt = new AtomicInteger();
+
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start(mapperName + linkLevel);
+
+        this.linkRepo.getLinkMap().values().stream()
+                .filter(link -> link.getLinkLevel() == linkLevel)
+                .forEach(link -> {
+                    total.getAndIncrement();
+
+                    if (link.getTrafFsn().getState().isState()) {
+                        missing.getAndIncrement();
+                        return;
+                    }
+                    if (link.getTrafFsn().getSpeed() == 0) {
+                        zeroSpeed.getAndIncrement();
+                        return;
+                    }
+
+                    fusion.getAndIncrement();
+                    LinkTrafCenterDto trafDto = link.getTrafCenter();
+                    try {
+                        mapper.insertTrafficCenter(trafDto);
+                        jobCnt.getAndIncrement();
+
+                        if (jobCnt.get() % maxBatchSize == 0) {
+                            sqlSession.flushStatements();
+                        }
+                    } catch (Exception e) {
+                        log.error("[SAVE...] LinkTrafSaveCenterWorker.processBatch: LinkLevel({}), jobCnt({}), Exception, [{}], {}.",
+                                linkLevel, jobCnt.get(), trafDto, e.getMessage());
+                    }
+                });
+
+        stopWatch.stop();
+        String msg = String.format("레벨%d 소통정보(TRAFFIC_CENTER)", linkLevel);
+        log.info("[SAVE...] (INS) {}, T/F/M/Z({}/{}/{}/{})",
+                LogUtils.elapsedLog(msg, jobCnt.get(), stopWatch.getTotalTimeMillis()),
+                total.get(), missing.get(), zeroSpeed.get(), fusion.get());
+        return jobCnt.get();
     }
 
 }

+ 67 - 61
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbCenterHistWorker.java

@@ -15,6 +15,7 @@ import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.springframework.util.StopWatch;
 
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -35,7 +36,7 @@ public class LinkTrafSaveDwdbCenterHistWorker implements Runnable {
         ConcurrentHashMap<Integer, DbmsBatchJobResult> mapData = new ConcurrentHashMap<>();
         SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) SpringUtils.getBean("dwdbSqlSessionFactory");
 
-        int linkTotalCount = this.linkRepo.getLinkArr().length;
+        int linkTotalCount = this.linkRepo.getLinkLists().size();
         int threadPoolSize = this.linkRepo.getConfig().getPrcsThreadCount();
         int batchPerThread = (int) Math.ceil((double) linkTotalCount / threadPoolSize);
 
@@ -45,42 +46,50 @@ public class LinkTrafSaveDwdbCenterHistWorker implements Runnable {
             DbmsBatchJobResult dbmsJobResult = DbmsBatchJobResult.builder()
                     .jobIndex(ii).start(startIdx).end(endIdx)
                     .total(0).target(0).link1(0).link2(0).link3(0).link4(0).effects(0).elapsedTime(0)
+                    .linkIds(this.linkRepo.getLinkLists().subList(startIdx, endIdx))
                     .build();
             mapData.put(ii, dbmsJobResult);
-            log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.run: [{}], {}", jobTable, dbmsJobResult);
         }
         ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
 
-        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
-            DwdbTrafficMapper mapper = sqlSession.getMapper(DwdbTrafficMapper.class);
-            mapData.forEach((key, dbmsJobResult) -> {
-                executorService.execute(() -> processBatch(sqlSession, dbmsJobResult, this.linkRepo, mapper));
-            });
-
-            try {
-                executorService.shutdown();
-                if (!executorService.awaitTermination(100, TimeUnit.SECONDS)) {
-                    executorService.shutdownNow();
-                }
-            } catch (InterruptedException e) {
-                log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.run: InterruptedException, [{}], {}.", jobTable, e.getMessage());
+        mapData.forEach((key, dbmsJobResult) -> {
+            executorService.execute(() -> processBatch(sqlSessionFactory, dbmsJobResult, this.linkRepo, jobTable));
+        });
+
+        try {
+            executorService.shutdown();
+            if (!executorService.awaitTermination(100, TimeUnit.SECONDS)) {
                 executorService.shutdownNow();
             }
-            sqlSession.commit();
+        } catch (InterruptedException e) {
+            log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.run: InterruptedException, [{}], {}.", jobTable, e.getMessage());
+            executorService.shutdownNow();
         }
-        catch (Exception e) {
-            log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.run: Exception, [{}], {}.", jobTable, e.getMessage());
-        }
-
-        int resultCount = 0;
 
+        int link1, link2, link3, link4;
+        long elapsedTime = 0;
+        link1 = link2 = link3 = link4 = 0;
+        for (Map.Entry<Integer, DbmsBatchJobResult> entry : mapData.entrySet()) {
+            DbmsBatchJobResult result = entry.getValue();
+            elapsedTime = Math.max(elapsedTime, result.getElapsedTime());
+            link1 += result.getLink1();
+            link2 += result.getLink2();
+            link3 += result.getLink3();
+            link4 += result.getLink4();
+        }
         stopWatch.stop();
+        int resultCount = link1 + link2 + link3 + link4;
         this.dbmsJobResult.setEffects(resultCount);
         this.dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.run:  (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
+
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("레벨1 TRAFFIC_CENTER_HIST@DWDB", link1, stopWatch.getTotalTimeMillis()));
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("레벨2 TRAFFIC_CENTER_HIST@DWDB", link2, stopWatch.getTotalTimeMillis()));
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("레벨3 TRAFFIC_CENTER_HIST@DWDB", link3, stopWatch.getTotalTimeMillis()));
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog("레벨4 TRAFFIC_CENTER_HIST@DWDB", link4, stopWatch.getTotalTimeMillis()));
+        log.info("[SAVE...] ..... {}", LogUtils.elapsedLog("TRAFFIC_CENTER_HIST@DWDB 저장", resultCount, stopWatch.getTotalTimeMillis()));
     }
 
-    private void processBatch(SqlSession sqlSession, DbmsBatchJobResult dbmsJobResult, LinkRepositoryService linkRepo, DwdbTrafficMapper mapper) {
+    private void processBatch(SqlSessionFactory sqlSessionFactory, DbmsBatchJobResult dbmsJobResult, LinkRepositoryService linkRepo, String jobTable) {
         final String mapperName = "insertTrafficCenterHist";
         final int maxBatchSize = linkRepo.getConfig().getDbmsBatchSize();
         int total, target;
@@ -91,45 +100,43 @@ public class LinkTrafSaveDwdbCenterHistWorker implements Runnable {
         StopWatch stopWatch = new StopWatch();
         stopWatch.start(mapperName + dbmsJobResult.getJobIndex());
 
-        log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: [{}], {} EA. {}", dbmsJobResult.getJobIndex(), dbmsJobResult.getEnd() - dbmsJobResult.getStart(), dbmsJobResult);
-        for (int ii = dbmsJobResult.getStart(); ii < dbmsJobResult.getEnd(); ii++) {
-            String linkId = linkRepo.getLinkArr()[ii];
-            LinkDto link = linkRepo.getLinkMap().get(linkId);
-            if (link == null) {
-                log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: Link is null, [{}].", linkId);
-                continue;
-            }
-            total++;
-
-//            if (!link.getTrafFsn().getState().isState()) {
-//                continue;
-//            }
-            target++;
-
-            LinkTrafCenterDto trafDto = null;
-            try {
-                trafDto = link.getTrafficDto(linkRepo.getPrcsTime());
-//                sqlSession.insert(mapperName, trafDto);
-                mapper.insertTrafficCenterHist(trafDto);
-                linkCounts[trafDto.getLinkLevel()-1]++;
-                jobCnt++;
-
-                if (jobCnt % maxBatchSize == 0) {
-//                    synchronized (sqlSession) {
-//                        sqlSession.flushStatements();
-//                        sqlSession.clearCache();
-//                    }
+//        log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: [{}], {} EA. {}", dbmsJobResult.getJobIndex(), dbmsJobResult.getEnd() - dbmsJobResult.getStart(), dbmsJobResult);
+        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
+            DwdbTrafficMapper mapper = sqlSession.getMapper(DwdbTrafficMapper.class);
+            for (String linkId : dbmsJobResult.getLinkIds()) {
+                LinkDto link = linkRepo.getLinkMap().get(linkId);
+                if (link == null) {
+                    log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: Link is null, [{}].", linkId);
+                    continue;
+                }
+                total++;
+
+                if (!link.getTrafFsn().getState().isState()) {
+                    continue;
+                }
+                target++;
+
+                LinkTrafCenterDto trafDto = link.getTrafCenter();
+                try {
+                    mapper.insertTrafficCenterHist(trafDto);
+                    linkCounts[trafDto.getLinkLevel()-1]++;
+                    jobCnt++;
+
+                    if (jobCnt % maxBatchSize == 0) {
+                        sqlSession.flushStatements();
+                    }
+                } catch (Exception e) {
+                    log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch({}): jobCnt({}), Exception, [{}], {}.",
+                            dbmsJobResult.getJobIndex(), jobCnt, trafDto, e.getMessage());
+                    break;
                 }
-            } catch (Exception e) {
-                log.error("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: Exception, [{}], {}.", trafDto, e.getMessage());
-                break;
             }
+            sqlSession.flushStatements();
+            sqlSession.commit();
+        }
+        catch (Exception e) {
+            log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch({}): Exception, [{}], {}.", dbmsJobResult.getJobIndex(), jobTable, e.getMessage());
         }
-//        synchronized (sqlSession) {
-//            sqlSession.flushStatements();
-//            sqlSession.clearCache();
-//            sqlSession.commit();
-//        }
         stopWatch.stop();
 
         dbmsJobResult.setTotal(total);
@@ -140,8 +147,7 @@ public class LinkTrafSaveDwdbCenterHistWorker implements Runnable {
         dbmsJobResult.setLink4(linkCounts[3]);
         dbmsJobResult.setEffects(jobCnt);
         dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveDwdbCenterHistWorker.processBatch: (SAV) {}, {}",
-                LogUtils.elapsedLog(mapperName + dbmsJobResult.getJobIndex(), jobCnt, stopWatch.getTotalTimeMillis()), dbmsJobResult);
+        log.info("[SAVE...] (SAV) {}, {}", LogUtils.elapsedLog(mapperName + dbmsJobResult.getJobIndex(), jobCnt, stopWatch.getTotalTimeMillis()), dbmsJobResult);
     }
 
 }

+ 3 - 3
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbFusionLogWorker.java

@@ -30,16 +30,16 @@ public class LinkTrafSaveDwdbFusionLogWorker implements Runnable {
             resultCount = this.mapper.insertLinkFusionLog(obj);
         }
         catch (InterruptedException e) {
-            log.info("[DELETE.] LinkTrafSaveDwdbFusionLogWorker.run: InterruptedException, [{}], {}.", jobTable, e.getMessage());
+            log.info("[SAVE...] LinkTrafSaveDwdbFusionLogWorker.run: InterruptedException, [{}], {}.", jobTable, e.getMessage());
         }
         catch (Exception e) {
-            log.info("[DELETE.] LinkTrafSaveDwdbFusionLogWorker.run: Exception, [{}], {}.", jobTable, e.getMessage());
+            log.info("[SAVE...] LinkTrafSaveDwdbFusionLogWorker.run: Exception, [{}], {}.", jobTable, e.getMessage());
         }
 
         stopWatch.stop();
         this.dbmsJobResult.setEffects(resultCount);
         this.dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveDwdbFusionLogWorker.run:  (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
+        log.info("[SAVE...] (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
     }
 
 }

+ 115 - 21
utic-ptis-server/src/main/java/com/utic/ptis/server/service/worker/LinkTrafSaveDwdbMissingValueHistWorker.java

@@ -1,50 +1,144 @@
 package com.utic.ptis.server.service.worker;
 
+import com.utic.common.spring.SpringUtils;
 import com.utic.ptis.server.dao.mapper.dwdb.DwdbTrafficMapper;
+import com.utic.ptis.server.dto.DbmsBatchJobResult;
 import com.utic.ptis.server.dto.DbmsJobResult;
+import com.utic.ptis.server.dto.LinkDto;
+import com.utic.ptis.server.dto.LinkMissingValueHistDto;
 import com.utic.ptis.server.service.LinkRepositoryService;
-import com.utic.ptis.server.service.LinkTrafPrcsTime;
 import com.utic.ptis.server.utils.LogUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
 import org.springframework.util.StopWatch;
 
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
 @Slf4j
 @RequiredArgsConstructor
 public class LinkTrafSaveDwdbMissingValueHistWorker implements Runnable {
 
     private final LinkRepositoryService linkRepo;
     private final DbmsJobResult dbmsJobResult;
-    private final LinkTrafPrcsTime prcsTime;
-    private final DwdbTrafficMapper mapper;
 
     @Override
     public void run() {
         String jobTable = this.dbmsJobResult.getTableName();
         StopWatch stopWatch = new StopWatch();
         stopWatch.start(jobTable);
-        int resultCount = 0;
-//        try {
-//            Thread.sleep(10);
-//
-//            if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenter();
-//            }
-//            else if (LinkTrafDeleteService.TABLE_TRAFFIC_CENTER_EXT.equals(this.jobTable)) {
-//                resultCount = this.mapper.deleteTrafficCenterExt();
-//            }
-//        }
-//        catch (InterruptedException e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: InterruptedException, [{}], {}.", this.jobTable, e.getMessage());
-//        }
-//        catch (Exception e) {
-//            log.info("[DELETE.] LinkTrafDeleteWorker.run: Exception, [{}], {}.", this.jobTable, e.getMessage());
-//        }
+        ConcurrentHashMap<Integer, DbmsBatchJobResult> mapData = new ConcurrentHashMap<>();
+        SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) SpringUtils.getBean("dwdbSqlSessionFactory");
+
+        int linkTotalCount = this.linkRepo.getLink1Lists().size();
+        int threadPoolSize = 4;//this.linkRepo.getConfig().getPrcsThreadCount();
+        int batchPerThread = (int) Math.ceil((double) linkTotalCount / threadPoolSize);
+
+        for (int ii = 0; ii < threadPoolSize; ii++) {
+            int startIdx = ii * batchPerThread;
+            int endIdx = Math.min(startIdx + batchPerThread, linkTotalCount);
+            DbmsBatchJobResult dbmsJobResult = DbmsBatchJobResult.builder()
+                    .jobIndex(ii).start(startIdx).end(endIdx)
+                    .total(0).target(0).link1(0).link2(0).link3(0).link4(0).effects(0).elapsedTime(0)
+                    .linkIds(this.linkRepo.getLink1Lists().subList(startIdx, endIdx))
+                    .build();
+            mapData.put(ii, dbmsJobResult);
+        }
+        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
+
+        mapData.forEach((key, dbmsJobResult) -> {
+            executorService.execute(() -> processBatch(sqlSessionFactory, dbmsJobResult, this.linkRepo, jobTable));
+        });
 
+        try {
+            executorService.shutdown();
+            if (!executorService.awaitTermination(100, TimeUnit.SECONDS)) {
+                executorService.shutdownNow();
+            }
+        } catch (InterruptedException e) {
+            log.error("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.run: InterruptedException, [{}], {}.", jobTable, e.getMessage());
+            executorService.shutdownNow();
+        }
+
+        int resultCount = 0;
+        long elapsedTime = 0;
+        for (Map.Entry<Integer, DbmsBatchJobResult> entry : mapData.entrySet()) {
+            DbmsBatchJobResult result = entry.getValue();
+            elapsedTime = Math.max(elapsedTime, result.getElapsedTime());
+            resultCount += result.getLink1();
+        }
         stopWatch.stop();
         this.dbmsJobResult.setEffects(resultCount);
         this.dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
-        log.info("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.run:  (SAV) {}", LogUtils.elapsedLog(jobTable, resultCount, stopWatch.getTotalTimeMillis()));
+
+        log.info("[SAVE...] (INS) {}", LogUtils.elapsedLog(jobTable, resultCount, elapsedTime));
+        log.info("[SAVE...] ..... {}", LogUtils.elapsedLog("LINK_MISSING_VALUE_HIST@DWDB 저장", resultCount, stopWatch.getTotalTimeMillis()));
+    }
+
+    private void processBatch(SqlSessionFactory sqlSessionFactory, DbmsBatchJobResult dbmsJobResult, LinkRepositoryService linkRepo, String jobTable) {
+        final String mapperName = "insertLinkMissingValueHist";
+        final int maxBatchSize = linkRepo.getConfig().getDbmsBatchSize();
+        int total = 0;
+        int jobCnt = 0;
+
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start(mapperName + dbmsJobResult.getJobIndex());
+
+        String exeDate = this.linkRepo.getPrcsTime().substring(0, 12);
+//        log.info("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.processBatch: [{}], {} EA. {}", dbmsJobResult.getJobIndex(), dbmsJobResult.getEnd() - dbmsJobResult.getStart(), dbmsJobResult);
+        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) {
+            DwdbTrafficMapper mapper = sqlSession.getMapper(DwdbTrafficMapper.class);
+            for (String linkId : dbmsJobResult.getLinkIds()) {
+                LinkDto link = linkRepo.getLinkMap().get(linkId);
+                if (link == null) {
+                    log.error("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.processBatch: Link is null, [{}].", linkId);
+                    continue;
+                }
+
+                LinkMissingValueHistDto valueHist = linkRepo.getMissingValueHist(link, exeDate);
+                if (valueHist == null) {
+                    continue;
+                }
+                total++;
+
+                try {
+                    mapper.insertLinkMissingValueHist(valueHist);
+                    jobCnt++;
+
+                    if (jobCnt % maxBatchSize == 0) {
+                        sqlSession.flushStatements();
+                    }
+                } catch (Exception e) {
+                    log.error("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.processBatch({}): jobCnt({}), Exception, [{}], {}.",
+                            dbmsJobResult.getJobIndex(), jobCnt, valueHist, e.getMessage());
+                    break;
+                }
+            }
+            sqlSession.flushStatements();
+            sqlSession.commit();
+        }
+        catch (Exception e) {
+            log.info("[SAVE...] LinkTrafSaveDwdbMissingValueHistWorker.processBatch({}): Exception, [{}], {}.", dbmsJobResult.getJobIndex(), jobTable, e.getMessage());
+        }
+
+        stopWatch.stop();
+
+        dbmsJobResult.setTotal(total);
+        dbmsJobResult.setTarget(total);
+        dbmsJobResult.setLink1(jobCnt);
+        dbmsJobResult.setLink2(0);
+        dbmsJobResult.setLink3(0);
+        dbmsJobResult.setLink4(0);
+        dbmsJobResult.setEffects(jobCnt);
+        dbmsJobResult.setElapsedTime(stopWatch.getTotalTimeMillis());
+        log.info("[SAVE...] (SAV) {}, {}",
+                LogUtils.elapsedLog(mapperName + dbmsJobResult.getJobIndex(), jobCnt, stopWatch.getTotalTimeMillis()), dbmsJobResult);
     }
 
 }

+ 12 - 2
utic-ptis-server/src/main/java/com/utic/ptis/server/utils/LogUtils.java

@@ -32,8 +32,18 @@ public class LogUtils {
     }
 
     public static String elapsedLog(String logMsg, int count, long elapsedTime) {
-        String adjustedMsg = adjustLogMsg(logMsg, 30);
+        String adjustedMsg = adjustLogMsg(logMsg, 36);
         DecimalFormat df = new DecimalFormat("#,###");
-        return String.format("%s: [%7s EA, %8s ms]", adjustedMsg, df.format(count), df.format(elapsedTime));
+        return String.format("%s: [%8s ms, %8s EA]", adjustedMsg, df.format(elapsedTime), df.format(count));
+    }
+    public static String elapsedLog(String logMsg) {
+        String adjustedMsg = adjustLogMsg(logMsg, 36);
+        DecimalFormat df = new DecimalFormat("#,###");
+        return String.format("%s", adjustedMsg);
+    }
+    public static String elapsedLog(String logMsg, long elapsedTime) {
+        String adjustedMsg = adjustLogMsg(logMsg, 36);
+        DecimalFormat df = new DecimalFormat("#,###");
+        return String.format("%s: [%8s ms]", adjustedMsg, df.format(elapsedTime));
     }
 }

+ 4 - 0
utic-ptis-server/src/main/resources/application.yml

@@ -68,6 +68,7 @@ spring:
       utic:
 #        driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
 #        jdbc-url: jdbc:log4jdbc:oracle:thin:@115.91.94.42:1521:HANTE
+        maximum-pool-size: 20
         driver-class-name: oracle.jdbc.OracleDriver
         jdbc-url: jdbc:oracle:thin:@115.91.94.42:1521:HANTE
         username: utiadmin
@@ -75,6 +76,7 @@ spring:
       dwdb:
 #        driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
 #        jdbc-url: jdbc:log4jdbc:oracle:thin:@115.91.94.42:1521:HANTE
+        maximum-pool-size: 20
         driver-class-name: oracle.jdbc.OracleDriver
         jdbc-url: jdbc:oracle:thin:@115.91.94.42:1521:HANTE
         username: DWUSER
@@ -88,11 +90,13 @@ spring:
   datasource:
     hikari:
       utic:
+        maximum-pool-size: 20
         driver-class-name: oracle.jdbc.OracleDriver
         jdbc-url: jdbc:oracle:thin:@192.168.10.21:1521:UTIS
         username: utiadmin
         password: utiadmin
       dwdb:
+        maximum-pool-size: 20
         driver-class-name: oracle.jdbc.OracleDriver
         jdbc-url: jdbc:oracle:thin:@192.168.10.14:1521:DWDB
         username: DWUSER

+ 1 - 1
utic-ptis-server/src/main/resources/logback-spring.xml

@@ -3,7 +3,7 @@
     <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
 
     <property name="APP_CLASS_PATH"  value="com.utic.ptis.server"/>
-    <property name="PROJECT_PREFIX"  value="utic-pits"/>
+    <property name="PROJECT_PREFIX"  value="utic-ptis"/>
     <property name="PROJECT_NAME"    value="${PROJECT_PREFIX}-server"/>
     <property name="ROOT_LOG_LEVEL"  value="INFO"/>
     <property name="LOG_CHARSET"     value="UTF-8" />

+ 1 - 1
utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/DwdbParamMapper.xml

@@ -12,7 +12,7 @@
           ]]>
     </select>
 
-    <select id="findEffectDays" resultType="com.utic.ptis.server.dto.dwdb.ParamEffectDays">
+    <select id="findEffectDays" resultType="com.utic.ptis.server.dto.dwdb.ParamPatternEffectDay">
     <![CDATA[
         SELECT TO_NUMBER(DECODE(CODEVALUE, NULL, '365', CODEVALUE)) AS effectDays
         FROM CODEDEFINE

+ 1 - 1
utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/DwdbTrafficMapper.xml

@@ -97,7 +97,7 @@
               )
     </insert>
 
-    <insert id="insertLinkMissingValueHist" parameterType="com.utic.ptis.server.dto.LinkMissingValueHist">
+    <insert id="insertLinkMissingValueHist" parameterType="com.utic.ptis.server.dto.LinkMissingValueHistDto">
         INSERT /*+ APPEND PARALLEL(LINK_MISSING_VALUE_HIST, 2) */ INTO LINK_MISSING_VALUE_HIST NOLOGGING (
                     linkid          ,
                     exe_date        ,

+ 24 - 36
utic-ptis-server/src/main/resources/mybatis/mapper/dwdb/LinkPatternMapper.xml

@@ -3,88 +3,76 @@
 
 <mapper namespace="com.utic.ptis.server.dao.mapper.dwdb.LinkPatternMapper">
 
-    <select id="findLinkPatternHoliday15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternHoliday15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_HOLIDAY a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
-    <select id="findLinkPatternSun15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternSun15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_SUN a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
-    <select id="findLinkPatternMon15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternMon15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_MON a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
-    <select id="findLinkPatternFri15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternFri15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_FRI a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
-    <select id="findLinkPatternSat15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternSat15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_SAT a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
-    <select id="findLinkPatternWeek15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkCollectParam" fetchSize="1500">
-    <![CDATA[
-        SELECT a.LINKID AS linkId
+    <select id="findLinkPatternWeek15M" resultType="com.utic.ptis.server.dto.LinkPtrnVal" parameterType="com.utic.ptis.server.dto.LinkPatternParam" fetchSize="1500">
+        SELECT a.LINKID AS linkId,
                a.SPEED  AS speed
         FROM PATN_15MIN_WEEK a, LINK b
         WHERE b.LINKLEVEL IN ('1', '4')
           AND a.LINKID    = b.LINKID
-          AND a.PATN_TIME = SUBSTR(#{nowDateTime}, 9, 4)
+          AND a.PATN_TIME = #{obj.patnTime}
           AND a.SPEED IS NOT NULL
           AND a.SPEED BETWEEN 1 AND 149
-          AND a.LOG_DATE > TO_DATE(#{nowDateTime}, 'YYYYMMDDHH24MISS') - #{missingEffDays}
-        ]]>
+          AND a.LOG_DATE > TO_DATE(#{obj.logDate}, 'YYYYMMDDHH24MISS')
     </select>
 
 </mapper>

+ 60 - 5
utic-ptis-server/src/test/java/com/utic/ptis/server/UticPtisServerApplicationTests.java

@@ -1,10 +1,12 @@
 package com.utic.ptis.server;
 
+import com.utic.common.utils.TimeUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.Test;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -14,18 +16,71 @@ import java.util.concurrent.TimeUnit;
 //@SpringBootTest
 public class UticPtisServerApplicationTests {
 
+    @Test
+    void arrayTest() {
+        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
+        int THREAD_POOL_SIZE = 3;
+        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
+        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
+            int startIdx = i * batchPerThread;
+            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);
+
+            String[] subArray = Arrays.copyOfRange(linkIds, startIdx, endIdx);
+            log.info("Thread {}: {}", i, Arrays.toString(subArray));
+        }
+    }
+    @Test
+    void arrayTest2() {
+        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
+        int THREAD_POOL_SIZE = 3;
+        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
+        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
+            int startIdx = i * batchPerThread;
+            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);
+
+            String[] subArray = new String[endIdx - startIdx];
+            System.arraycopy(linkIds, startIdx, subArray, 0, endIdx - startIdx);
+            log.info("Thread {}: {}", i, Arrays.toString(subArray));
+        }
+
+    }
+    @Test
+    void arrayTest3() {
+        String[] linkIds = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
+        int THREAD_POOL_SIZE = 3;
+        int batchPerThread = (int) Math.ceil((double) linkIds.length / THREAD_POOL_SIZE);
+        for (int i = 0; i < THREAD_POOL_SIZE; i++) {
+            int startIdx = i * batchPerThread;
+            int endIdx = Math.min(startIdx + batchPerThread, linkIds.length);
+
+            String[] subArray = new String[endIdx - startIdx];
+            System.arraycopy(linkIds, startIdx, subArray, 0, endIdx - startIdx);
+            log.info("Thread {}: {}", i, Arrays.toString(subArray));
+        }
+
+    }
+
     @Test
     void testDecompress() {
-        //ReadableBytes: 113 Bytes
-        String data = "02C518081A01061A11571DB1020C00020003010004006C00001900C800400200140050088040000802A0040021001001408100020C10608000010808A0000000000000000000000000000000000000000000000000000000000000000000000000000001FFC234B7EEAFFBEBB2EDEFFF0C123C030A1E020307140203020C1B320203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003010104006C00008128084441200A0451508882401408A2A0000001001000400102021010808000040820A0000000000000000000000000000000000000000000000000000000000000000000000000000001FF020303030B0C5CEDAFBBFB3BFF0C123C030A1E03071403020C1B32020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E803";
+        String dateTimeStr = "20240512000000";
+        for (int ii = 0; ii < 62; ii++) {
+            String currTime = TimeUtils.addMinutes(dateTimeStr, ii);
+            String nextTime = TimeUtils.addMinutes(currTime, 5);
+            String nextPrcsTime = TimeUtils.getFiveMinString(TimeUtils.stringToDate(nextTime));
+            String patternTime = TimeUtils.roundToQuarterHour(nextPrcsTime);
+            log.info("Original: {}/{}/{} => {}", currTime, nextTime, nextPrcsTime, patternTime);
+//            String roundedTime = TimeUtils.roundToQuarterHour(prcsTime);
+//            String quaterTime = TimeUtils.getQuarterHour(prcsTime);
+//            log.info("Original: {}/{}, => {}/{}, {}", currTime, prcsTime, roundedTime, quaterTime, roundedTime.equals(quaterTime));
+        }
     }
 
 
     @Test
     void tt() {
-        for (int ii = 0; ii < 608; ii++) {
-            log.info("{}, {}, {}", ii, ii/19, ii%19);
-        }
+        String patternTime = "20250513162500";
+        String patternHourMin = patternTime.substring(8, 12);
+        log.info("patternTime: {}, patternHourMin: {}", patternTime, patternHourMin);
     }
     @Test
     void testDecompress2010() {