| 
					
				 | 
			
			
				@@ -0,0 +1,391 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package com.utic.ptis.server.service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.utic.common.utils.Elapsed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.utic.ptis.server.dto.LinkCollectDto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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 lombok.Getter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.RequiredArgsConstructor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import org.springframework.stereotype.Service; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.ArrayList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.Optional; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.atomic.AtomicInteger; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Getter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@RequiredArgsConstructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Service 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class LinkTrafMissingService implements AbstractProcessService { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final LinkRepositoryService linkRepo; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final LinkTrafParamService trafParamService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final LinkTrafCollectService collectService; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private void initialize() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.initialize: start."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.initialize: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public int processing() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.processing: start."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 0. 결측 초기화 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        initialize(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 모든 결측 알고리즘에 대해 결측 처리를 수행하고  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 최종 선택된 결측 알고리즘으로 결측을 수행한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 1. PSD 알고리즘 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingLinkPsd(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 2. 레벨1 구간 소통정보를 이용하여 레벨4 구간 소통정보 생성 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        groupLinkTrafficCreate(4, "P"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 3. 레벨4 링크를 이용하여 레벨1 링크 PSD 결측정보 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingGroupPsd(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 4. 결측된 구간에 대하여 결측 알고리즘을 이용하여 속도 계산 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingLinkCorrect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 5. 패턴을 이용하여 결측 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingLinkPattern(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 6. 외부 연계 소통정보를 이용하여 결측 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingLinkExternal(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 7. 국토부 민간소통정보를 이용한 결측 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //    - 외부연계퓨전은 국토부 민간소통정보를 이용하여 결측처리하지 않으므로외부연계퓨전처리 완료후 결측을 처리함 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        missingLinkMoct(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 8. 결측 처리된 레벨1 소통정보를 이용하여 상위레벨 소통정보를 생성(레벨2,3,4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int ii = 2; ii <= 4; ii++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            groupLinkTrafficCreate(ii, "P"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.processing: ..end. {}", Elapsed.elapsedStr(elapsed.nanoSeconds())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int missingLinkMoct() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: start."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 결측처리 방식: 국토부 민간소통정보를 이용하여 결측 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        LinkCollectResultDto collectMOCT = Optional.ofNullable(this.collectService.get(LinkTrafCollectSetupService.MOCT)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .orElseGet(() -> LinkCollectResultDto.builder().clctSystCd(LinkTrafCollectSetupService.MOCT).lists(new ArrayList<>()).build()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int nCalCnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (LinkCollectDto clctTraf: collectMOCT.getLists()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            LinkDto link = this.linkRepo.getLink(clctTraf.getLinkId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (link == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                log.error("[MISSING] LinkTrafMissingService.missingLinkMoct: {} link not found.", clctTraf.getLinkId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (link.getTrafFsn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 퓨전 소통정보가 존재하면 처리하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (clctTraf.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(clctTraf.getCenterId(), clctTraf.getSpeed(), clctTraf.getMissValueYn(), clctTraf.getDataResType()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                link.getTrafExt().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                nCalCnt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.missingLinkMoct: ..end. {} EA. {}", nCalCnt, Elapsed.elapsedStr(elapsed.nanoSeconds())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return nCalCnt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int missingLinkExternal() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.missingLinkExternal: start."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 결측처리 방식: 구간의 현재 패턴정보를 이용 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        AtomicInteger nCalCnt = new AtomicInteger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.linkRepo.getLinkMap().values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(link -> link.getLinkLevel() == 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach(link -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 구간의 연계소통정보가 존재하면 처리하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (link.getTrafExt().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 구간의 퓨전소통정보가 존재하지 않으면 처리하지 못함 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (!link.getTrafFsn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 동부데이터가 들어가 있는것은 제외하여야 한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 즉, 정상적으로 수집된 정보는 제외한다.(동부정보가 들어가있으므로) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (link.getTrafFsn().getState().getCrtDataType() == LinkTrafState.TRAFFIC_CRT_DATA_TYPE.CRT_DATA_NORMAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    link.getTrafExt().copy(link.getTrafFsn()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    nCalCnt.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 결측처리 방식: 구간의 현재 패턴정보를 이용 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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.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(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 결측처리 방식: 우선순위, KNN(사용하지 않음) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        AtomicInteger nCalCnt = new AtomicInteger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.linkRepo.getLinkMap().values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(link -> link.getLinkLevel() == 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach(link -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 구간의 퓨전소통정보가 존재하면 처리하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (link.getTrafFsn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (link.getMissPsd().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.getMissPsd().getSpeed(), link.getMissPsd().getMissValueYn(), "P"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                link.getTrafExt().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                nCalCnt.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /* PSD 알고리즘 결측정보 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *  1. 레벨1 구간에 대한 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *  2. 결측된 링크의 현재 패턴정보가 존재해야 처리할 수 있음. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *  3. 상/하류 구간의 현재/패턴 정보가 존재해야함. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *    3.1 상/하류 구간 정보가 모두 존재하는 경우 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *        결측속도 = 결측구간 패턴속도 * { [AVG(상류부현재속도+하류부현재속도)] / [AVG(상류부패턴속도+하류부패턴속도)]  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *    3.2 상/하류 구간 중 하나의 구간 정보 만 존해하는 경우 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *        결측속도 = 결측구간 패턴속도 * { 상/하류구간현재속도 / 상/하류구간패턴속도 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *  4. 3항에서 결측한 결측 속도를 포함한 레벨4 구간의 속도정보를 계산 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *  5. 결측이 발생한 레벨1 구간에 대해 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         *        결측속도 = 결측구간 패턴속도 * { 레벨4현재속도 / 레벨4패턴속도 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        AtomicInteger nCalCnt = new AtomicInteger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.linkRepo.getLinkMap().values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(link -> link.getLinkLevel() == 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach(link -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 구간의 패턴정보가 존재하지 않는 다면 결측 처리 못함 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (!link.getTrafPtrn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    LinkDto upLink = this.linkRepo.getLink(link.getUpLinkId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    LinkDto dnLink = this.linkRepo.getLink(link.getDnLinkId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    int step, speed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    float cSpeed, pSpeed, ptrnSpeed; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    step = speed = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    cSpeed = pSpeed = 0F; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ptrnSpeed = (float)link.getTrafPtrn().getSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (upLink != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (upLink.getTrafFsn().getState().isState() && upLink.getTrafPtrn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 상류 구간의 현재속도 정보와 패턴정보가 존재한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            step += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            cSpeed += (float)upLink.getTrafFsn().getSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            pSpeed += (float)upLink.getTrafPtrn().getSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (dnLink != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (dnLink.getTrafFsn().getState().isState() && dnLink.getTrafPtrn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 상류 구간의 현재속도 정보와 패턴정보가 존재한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            step += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            cSpeed += (float)dnLink.getTrafFsn().getSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            pSpeed += (float)dnLink.getTrafPtrn().getSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    String missValueYn = ""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (step == 1 || step == 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 상류부(H) 또는 하류부(L) 소통정보 만 존재하는 경우 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        speed = (int)( (ptrnSpeed * (cSpeed / pSpeed)) + 0.5 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        missValueYn = (step == 1) ? "H" : "L"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else if (step == 3) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 상/하류부 소통정보가 모두 존재하는 경우 'Y' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        speed = (int)( (ptrnSpeed * ((cSpeed/2.) / (pSpeed/2.))) + 0.5 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        missValueYn = "Y"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (speed > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (speed > link.getMaxSpeed()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            speed = link.getMaxSpeed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        link.getMissPsd().setTraffic(missValueYn, speed); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        nCalCnt.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        AtomicInteger nCalCnt = new AtomicInteger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.linkRepo.getLinkMap().values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(link -> link.getLinkLevel() == linkLevel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach(link -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 링크그룹에 속한 레벨1 링크의 소통정보를 이용하여 링크그룹 소통정보를 생성한다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (link.getLinkIds() == null || link.getLinkIds().isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    float sumSpeed, sumLength, sumSpeedExt, sumLengthExt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    int   clctCnt, clctCntExt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    sumSpeed = sumLength = sumSpeedExt = sumLengthExt = 0.F; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    clctCntExt = clctCnt = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for (String linkId : link.getLinkIds()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        LinkDto subLink = this.linkRepo.getLink(linkId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (subLink == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            log.error("[MISSING] LinkTrafMissingService.groupLinkTrafficCreate[Level:{}]: {} link not found.", linkLevel, linkId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!subLink.getTrafFsn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 퓨전 소통정보 생성 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (subLink.getTrafFsn().getSpeed() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sumSpeed  += subLink.getTrafFsn().getSpeed() * subLink.getLength(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sumLength += subLink.getLength(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                clctCnt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (!subLink.getTrafExt().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            // 외부연계 소통정보 생성 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (subLink.getTrafExt().getSpeed() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sumSpeedExt  += subLink.getTrafExt().getSpeed() * subLink.getLength(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                sumLengthExt += subLink.getLength(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                clctCntExt++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    TrafficGrade grade = Optional.ofNullable(this.trafParamService.getTrafGradeMap().get(link.getLinkId())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            .orElseGet(() -> TrafficGrade.builder().roadRank("999").minSpeed(30).maxSpeed(49).build()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (sumSpeed > 0. && sumLength > 0. && clctCnt > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        int speed = (int)( (sumSpeed / sumLength) + 0.5 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        link.getTrafFsn().setTraffic("C00", speed, "M", dataResType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        link.getTrafFsn().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        nCalCnt.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (sumSpeedExt > 0. && sumLengthExt > 0. && clctCntExt > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        int speedExt = (int)( (sumSpeedExt / sumLengthExt) + 0.5 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        link.getTrafExt().setTraffic("C00", speedExt, "M", dataResType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        link.getTrafExt().trafficCorrect(link.getLength(), link.getMaxSpeed(), grade.getMinSpeed(), grade.getMaxSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        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."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Elapsed elapsed = new Elapsed(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        AtomicInteger nCalCnt = new AtomicInteger(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 레벨4 구간을 이용한 PSD 결측정보 처리 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 레벨1은 모든 구간에 대하여 PSD 알고리즘을 수행하고 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 레벨4 소통정보 다운 알고리즘은 생성되지 않은 레벨1 구간에 대하여 수행함 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // PSD 상/하위 구간으로 처리하지 못한 구간에 대하여 4레벨 다운 소통정보를 생성 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 레벨1 PSD 속도 = 레벨1 패턴속도 * (레벨4 퓨전속도 / 레벨4 패턴속도) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.linkRepo.getLinkMap().values().parallelStream() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .filter(link -> link.getLinkLevel() == 4) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                .forEach(link -> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (link.getLinkIds() == null || link.getLinkIds().isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 레벨4 구간에 속한 레벨1 구간이 존재하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!link.getTrafFsn().getState().isState() || !link.getTrafPtrn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 레벨4 구간의 퓨전속도 또는 패턴속도가 존재하지 않으면 결측처리를 수행할 수 없다. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for (String linkId : link.getLinkIds()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    LinkDto subLink = this.linkRepo.getLink(linkId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (subLink == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        log.error("[MISSING] LinkTrafMissingService.missingGroupPsd: {} link not found.", linkId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (subLink.getMissPsd().getSpeed() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 레벨1 구간의 PSD 속도정보가 존재하면 결측처리 수행하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (!subLink.getTrafPtrn().getState().isState()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        // 레벨1 구간의 패턴속도가 존재하지 않으면 결측처리 수행하지 않음 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    int speed = (int)( (subLink.getTrafPtrn().getSpeed() * ((double) link.getTrafFsn().getSpeed() / link.getTrafPtrn().getSpeed())) + 0.5 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    subLink.getMissPsd().setSpeed(speed); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    subLink.getMissPsd().setMissValueYn("K"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (subLink.getMissPsd().getSpeed() > subLink.getMaxSpeed()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        subLink.getMissPsd().setSpeed(subLink.getMaxSpeed()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    nCalCnt.incrementAndGet(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("[MISSING] LinkTrafMissingService.missingGroupPsd: ..end. {} EA. {}", nCalCnt.get(), Elapsed.elapsedStr(elapsed.nanoSeconds())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return nCalCnt.get(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |