diff --git a/build.gradle b/build.gradle index 7546b58a..be11e839 100644 --- a/build.gradle +++ b/build.gradle @@ -29,6 +29,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-webflux' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java index feb6c224..fbe82c07 100644 --- a/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java +++ b/src/main/java/com/kamco/cd/kamcoback/common/utils/FIleChecker.java @@ -27,14 +27,14 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; import lombok.Getter; import org.apache.commons.io.FilenameUtils; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.gce.geotiff.GeoTiffReader; import org.springframework.util.FileSystemUtils; import org.springframework.web.multipart.MultipartFile; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; public class FIleChecker { @@ -521,14 +521,13 @@ public class FIleChecker { return true; } - - public static void unzip(String fileName, String destDirectory ) throws IOException { + public static void unzip(String fileName, String destDirectory) throws IOException { File destDir = new File(destDirectory); if (!destDir.exists()) { destDir.mkdirs(); // 대상 폴더가 없으면 생성 } - String zipFilePath = destDirectory+"/"+fileName; + String zipFilePath = destDirectory + "/" + fileName; try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath))) { ZipEntry zipEntry = zis.getNextEntry(); @@ -564,7 +563,6 @@ public class FIleChecker { } } - public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { File destFile = new File(destinationDir, zipEntry.getName()); @@ -578,8 +576,6 @@ public class FIleChecker { return destFile; } - - public static boolean checkExtensions(String fileName, String ext) { if (fileName == null) return false; diff --git a/src/main/java/com/kamco/cd/kamcoback/config/WebClientConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/WebClientConfig.java new file mode 100644 index 00000000..3270a4ec --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/config/WebClientConfig.java @@ -0,0 +1,24 @@ +package com.kamco.cd.kamcoback.config; + +import io.netty.channel.ChannelOption; +import java.time.Duration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.http.client.HttpClient; + +@Configuration +public class WebClientConfig { + + @Bean + public WebClient webClient() { + + HttpClient httpClient = + HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) + .responseTimeout(Duration.ofSeconds(5)); + + return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build(); + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java index a1ae6ac5..5215dc2e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/InferenceResultApiController.java @@ -4,8 +4,10 @@ import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList; import com.kamco.cd.kamcoback.inference.service.InferenceResultService; +import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -13,6 +15,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import java.time.LocalDate; +import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -30,6 +33,7 @@ import org.springframework.web.bind.annotation.RestController; public class InferenceResultApiController { private final InferenceResultService inferenceResultService; + private final MapSheetMngService mapSheetMngService; @Operation(summary = "추론관리 목록", description = "어드민 홈 > 추론관리 > 추론관리 > 추론관리 목록") @ApiResponses( @@ -63,6 +67,24 @@ public class InferenceResultApiController { return ApiResponseDto.ok(analResList); } + @Operation(summary = "년도 목록 조회", description = "어드민 홈 > 추론관리 > 추론목록 > 변화탐지 실행 정보 입력 > 년도 목록 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = + @Content( + mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = Integer.class)))), + @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), + @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) + }) + @GetMapping("/years") + public ApiResponseDto> findMapSheetMngDoneYyyyList() { + return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngDoneYyyyList()); + } + @Operation(summary = "변화탐지 실행 정보 입력", description = "어드민 홈 > 추론관리 > 추론목록 > 변화탐지 실행 정보 입력") @ApiResponses( value = { diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java index 599c8ff4..bd19f3a5 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceResultDto.java @@ -114,21 +114,21 @@ public class InferenceResultDto { @Schema(description = "M1", example = "2") @NotNull - private Long model1Uid; + private Long model1Uuid; @Schema(description = "M2", example = "4") @NotNull - private Long model2Uid; + private Long model2Uuid; @Schema(description = "M3", example = "7") @NotNull - private Long model3Uid; + private Long model3Uuid; - @Schema(description = "비교년도", example = "2003") + @Schema(description = "비교년도", example = "2023") @NotNull private Integer compareYyyy; - @Schema(description = "탐지년도", example = "2004") + @Schema(description = "탐지년도", example = "2024") @NotNull private Integer targetYyyy; @@ -144,7 +144,9 @@ public class InferenceResultDto { message = "탐지 데이터 옵션은 '추론제외', '이전 년도 도엽 사용' 만 사용 가능합니다.") private String detectOption; - @Schema(description = "5k 도협 번호 목록", example = "[\"34607067\",\"35802056\"]") + @Schema( + description = "5k 도협 번호 목록", + example = "[\"37914034\",\"37914024\",\"37914023\",\"37914014\",\"37914005\",\"37914004\"]") @NotNull private List mapSheetNum; } diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java new file mode 100644 index 00000000..27102187 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/inference/dto/InferenceSendDto.java @@ -0,0 +1,33 @@ +package com.kamco.cd.kamcoback.inference.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class InferenceSendDto { + + private PredRequestsAreas predRequestsAreas; + private String model_version; + private String cd_model_path; + private String cd_model_config; + private String cls_model_path; + private String cls_model_version; + private String cd_model_type; + private Integer priority; + + @Getter + @Setter + @AllArgsConstructor + public static class PredRequestsAreas { + + private Integer input1_year; + private Integer input2_year; + private String input1_scene_path; + private String input2_scene_path; + } +} diff --git a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java index ce39c4d8..02e22caa 100644 --- a/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java +++ b/src/main/java/com/kamco/cd/kamcoback/inference/service/InferenceResultService.java @@ -1,26 +1,44 @@ package com.kamco.cd.kamcoback.inference.service; +import com.kamco.cd.kamcoback.common.exception.CustomApiException; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Detail; import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto; import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList; +import com.kamco.cd.kamcoback.inference.dto.InferenceSendDto; +import com.kamco.cd.kamcoback.model.dto.ModelMngDto.Basic; import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService; +import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService; +import com.kamco.cd.kamcoback.postgres.core.ModelMngCoreService; import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.UUID; import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; @Service +@Log4j2 @RequiredArgsConstructor @Transactional(readOnly = true) public class InferenceResultService { private final InferenceResultCoreService inferenceResultCoreService; + private final MapSheetMngCoreService mapSheetMngCoreService; + private final ModelMngCoreService modelMngCoreService; + private final WebClient webClient; + + @Value("${inference.url}") + private String inferenceUrl; /** * 추론관리 목록 @@ -39,7 +57,85 @@ public class InferenceResultService { */ @Transactional public UUID saveInferenceInfo(InferenceResultDto.RegReq req) { - return inferenceResultCoreService.saveInferenceInfo(req); + UUID uuid = inferenceResultCoreService.saveInferenceInfo(req); + + // TODO tif 없으면 전년도 파일 조회 쿼리 추가해야함 + // TODO 도엽 개수를 target 기준으로 맞춰야함 + this.getSceneInference(String.valueOf(req.getCompareYyyy()), req.getMapSheetNum()); + this.getSceneInference(String.valueOf(req.getTargetYyyy()), req.getMapSheetNum()); + + InferenceSendDto m1 = this.getModelInfo(req.getModel1Uuid()); + InferenceSendDto m2 = this.getModelInfo(req.getModel2Uuid()); + InferenceSendDto m3 = this.getModelInfo(req.getModel3Uuid()); + + // ensureAccepted(m1); + // ensureAccepted(m2); + // ensureAccepted(m3); + + return uuid; + } + + /** + * 추론 AI API 호출 + * + * @param dto + */ + private Mono inferenceSend(InferenceSendDto dto) { + return webClient + .post() + .uri("http://localhost:8080/test") // inferenceUrl + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(dto) + .retrieve() + .toBodilessEntity() + .map(res -> res.getStatusCode().is2xxSuccessful()) + .doOnNext(ok -> log.info("발송결과={}", ok)) + .onErrorReturn(false); + } + + private void ensureAccepted(InferenceSendDto dto) { + + Boolean ok = + this.inferenceSend(dto) + .timeout(java.time.Duration.ofSeconds(3)) // 접수는 빨리 와야 함 + .onErrorReturn(false) // 타임아웃/통신오류도 실패 처리 + .block(java.time.Duration.ofSeconds(4)); // 최종 안전장치 (짧게!) + + if (!Boolean.TRUE.equals(ok)) { + // 여기서 예외가 터져야 @Transactional 롤백됨 + throw new CustomApiException("BAD_GATEWAY", HttpStatus.BAD_GATEWAY); + } + } + + /** + * 모델정보 조회 dto 생성 후 반환 + * + * @param id + * @return + */ + private InferenceSendDto getModelInfo(Long id) { + + Basic modelInfo = modelMngCoreService.findByModelUuid(id); + + InferenceSendDto sendDto = new InferenceSendDto(); + sendDto.setModel_version(modelInfo.getModelVer()); + sendDto.setCd_model_path(modelInfo.getCdModelPath()); + sendDto.setCd_model_config(modelInfo.getCdModelConfig()); + sendDto.setCls_model_path(modelInfo.getClsModelPath()); + // sendDto.setCls_model_version(modelInfo.getCls); + sendDto.setCd_model_type(modelInfo.getModelType()); + // sendDto.setPriority(modelInfo.getPriority()); + return sendDto; + } + + /** + * geojson 파일 생성 + * + * @param yyyy + * @param mapSheetNums + */ + private void getSceneInference(String yyyy, List mapSheetNums) { + mapSheetMngCoreService.getSceneInference(yyyy, mapSheetNums); } /** diff --git a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java index 79f73e33..92216f10 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/dto/ModelMngDto.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.kamco.cd.kamcoback.common.utils.enums.CodeExpose; import com.kamco.cd.kamcoback.common.utils.enums.EnumType; import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm; -import com.kamco.cd.kamcoback.upload.dto.UploadDto; import io.swagger.v3.oas.annotations.media.Schema; import java.math.BigDecimal; import java.time.ZonedDateTime; @@ -67,7 +66,7 @@ public class ModelMngDto { private String clsModelPath; private String clsModelFileName; private String clsModelVersion; - private double priority; + private Double priority; private String memo; public Basic( @@ -142,7 +141,7 @@ public class ModelMngDto { private String clsModelPath; private String clsModelFileName; private String clsModelVersion; - private double priority; + private Double priority; } @Schema(name = "ModelAddReq", description = "모델 등록 req") @@ -164,8 +163,8 @@ public class ModelMngDto { private String clsModelFileName; private String memo; - @JsonIgnore private String clsModelVersion; - @JsonIgnore private double priority; + @JsonIgnore private String clsModelVersion; + @JsonIgnore private Double priority; @JsonIgnore private UUID uuid; } @@ -193,13 +192,13 @@ public class ModelMngDto { } } - @Schema(name = "ModelMetricAddReq", description = "모델 등록 req") @Getter @Setter @NoArgsConstructor @AllArgsConstructor public static class ModelMetricAddReq { + private Long modelUid; private Long modelVerUid; private double f1Score; @@ -215,6 +214,7 @@ public class ModelMngDto { @NoArgsConstructor @AllArgsConstructor public static class ModelUploadResDto { + private String res; private String resMsg; private UUID uuid; @@ -236,5 +236,4 @@ public class ModelMngDto { return (double) (this.chunkIndex + 1) / (this.chunkTotalIndex + 1) * 100.0; } } - } diff --git a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java index 312a5895..d32059b7 100644 --- a/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/model/service/ModelMngService.java @@ -3,8 +3,6 @@ package com.kamco.cd.kamcoback.model.service; import com.kamco.cd.kamcoback.common.utils.FIleChecker; import com.kamco.cd.kamcoback.common.utils.FIleChecker.Basic; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; -import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto; -import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto; import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.model.dto.ModelMngDto.ModelMetricAddReq; import com.kamco.cd.kamcoback.model.dto.ModelMngDto.ModelUploadResDto; @@ -71,7 +69,7 @@ public class ModelMngService { UUID uuid = UUID.randomUUID(); addReq.setUuid(uuid); addReq.setClsModelVersion(addReq.getModelVer()); - addReq.setPriority(0L); + addReq.setPriority(0d); Long modelUid = modelMngCoreService.insertModel(addReq); ModelMetricAddReq modelMetricAddReq = new ModelMetricAddReq(); @@ -83,7 +81,6 @@ public class ModelMngService { modelMetricAddReq.setLoss(0); modelMetricAddReq.setIou(0); - modelMngCoreService.insertModelResultMetric(modelMetricAddReq); return new ApiResponseDto.ResponseObj(ApiResponseDto.ApiResponseCode.OK, "등록되었습니다."); @@ -91,20 +88,19 @@ public class ModelMngService { public ModelUploadResDto uploadChunkModelFile( UploadDto.UploadAddReq upAddReqDto, MultipartFile chunkFile) { - UploadDto.UploadRes upRes = uploadService.uploadChunk(upAddReqDto, chunkFile); + UploadDto.UploadRes upRes = uploadService.uploadChunk(upAddReqDto, chunkFile); + ModelUploadResDto modelUploadResDto = new ModelUploadResDto(); + modelUploadResDto.setRes(upRes.getRes()); + modelUploadResDto.setResMsg(upRes.getResMsg()); + modelUploadResDto.setUuid(upRes.getUuid()); + modelUploadResDto.setFilePath(upRes.getFilePath()); + modelUploadResDto.setFileName(upRes.getFileName()); + modelUploadResDto.setChunkIndex(upRes.getChunkIndex()); + modelUploadResDto.setChunkTotalIndex(upRes.getChunkTotalIndex()); + // 압축풀기 (String zipFilePath, String destDirectory) - ModelUploadResDto modelUploadResDto = new ModelUploadResDto(); - modelUploadResDto.setRes(upRes.getRes()); - modelUploadResDto.setResMsg(upRes.getResMsg()); - modelUploadResDto.setUuid(upRes.getUuid()); - modelUploadResDto.setFilePath(upRes.getFilePath()); - modelUploadResDto.setFileName(upRes.getFileName()); - modelUploadResDto.setChunkIndex(upRes.getChunkIndex()); - modelUploadResDto.setChunkTotalIndex(upRes.getChunkTotalIndex()); - //압축풀기 (String zipFilePath, String destDirectory) - - if( upRes.getChunkIndex() == upRes.getChunkTotalIndex() ) { + if (upRes.getChunkIndex() == upRes.getChunkTotalIndex()) { try { FIleChecker.unzip(upRes.getFileName(), upRes.getFilePath()); @@ -115,47 +111,37 @@ public class ModelMngService { } } - - return modelUploadResDto; } public ModelUploadResDto getUnzipModelFiles(String dirPath, ModelUploadResDto modelUploadResDto) { - //String dirPath = srchDto.getDirPath(); + // String dirPath = srchDto.getDirPath(); int startPos = 0; int endPos = 20; List files = - FIleChecker.getFilesFromAllDepth( - dirPath, - "*", - "pth,py", - 10, - "name", - startPos, - endPos); + FIleChecker.getFilesFromAllDepth(dirPath, "*", "pth,py", 10, "name", startPos, endPos); for (Basic dto : files) { // 예: 파일명 출력 및 추가 작업 String foldNm = dto.getFullPath().replace(dto.getFileNm(), ""); - if( dto.getExtension().equals("pth") ) { + if (dto.getExtension().equals("pth")) { modelUploadResDto.setCdModelPath(foldNm); modelUploadResDto.setCdModelFileName(dto.getFileNm()); - }else if( dto.getExtension().equals("py") ) { + } else if (dto.getExtension().equals("py")) { modelUploadResDto.setCdModelConfigPath(foldNm); modelUploadResDto.setCdModelConfigFileName(dto.getFileNm()); - }else if( dto.getExtension().equals("json") ) { + } else if (dto.getExtension().equals("json")) { modelUploadResDto.setClsModelPath(foldNm); modelUploadResDto.setClsModelFileName(dto.getFileNm()); } - } - //int fileListPos = 0; - //int fileTotCnt = files.size(); - //long fileTotSize = FIleChecker.getFileTotSize(files); + // int fileListPos = 0; + // int fileTotCnt = files.size(); + // long fileTotSize = FIleChecker.getFileTotSize(files); return modelUploadResDto; } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java index dbc77fa4..8eaeb774 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/InferenceResultCoreService.java @@ -57,9 +57,9 @@ public class InferenceResultCoreService { public UUID saveInferenceInfo(InferenceResultDto.RegReq req) { MapSheetLearnEntity mapSheetLearnEntity = new MapSheetLearnEntity(); mapSheetLearnEntity.setTitle(req.getTitle()); - mapSheetLearnEntity.setM1ModelUid(req.getModel1Uid()); - mapSheetLearnEntity.setM2ModelUid(req.getModel2Uid()); - mapSheetLearnEntity.setM3ModelUid(req.getModel3Uid()); + mapSheetLearnEntity.setM1ModelUid(req.getModel1Uuid()); + mapSheetLearnEntity.setM2ModelUid(req.getModel2Uuid()); + mapSheetLearnEntity.setM3ModelUid(req.getModel3Uuid()); mapSheetLearnEntity.setCompareYyyy(req.getCompareYyyy()); mapSheetLearnEntity.setTargetYyyy(req.getTargetYyyy()); mapSheetLearnEntity.setMapSheetScope(req.getMapSheetScope()); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java index 25e1aab1..6108d6ee 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MapSheetMngCoreService.java @@ -200,4 +200,35 @@ public class MapSheetMngCoreService { throw new RuntimeException("GeoJSON 파일 생성 실패: " + e.getMessage(), e); } } + + public void getSceneInference(String yyyy, List scenes) { + try { + List sceneInference = mapSheetMngRepository.getSceneInference(yyyy, scenes); + + if (sceneInference == null || sceneInference.isEmpty()) { + log.warn("No scene data found for year: {}", yyyy); + return; + } + + if (activeEnv.equals("local")) { + syncRootDir = System.getProperty("user.home") + "/geojson"; + } + String filename = String.format("%s_%s.geojson", yyyy, activeEnv); + String outputPath = Paths.get(syncRootDir, filename).toString(); + + // 디렉토리가 없으면 생성 + Files.createDirectories(Paths.get(syncRootDir)); + + // GeoJSON 파일 생성 (EPSG:5186 - Korea 2000 / Central Belt 2010) + GeoJsonFileWriter writer = new GeoJsonFileWriter(); + writer.exportToFile(sceneInference, "scene_inference_" + yyyy, 5186, outputPath); + + log.info("GeoJSON file created successfully: {}", outputPath); + log.info("Total features exported: {}", sceneInference.size()); + + } catch (IOException e) { + log.error("Failed to create GeoJSON file for year: {}", yyyy, e); + throw new RuntimeException("GeoJSON 파일 생성 실패: " + e.getMessage(), e); + } + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java index 0b05413e..86d5306d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/ModelMngCoreService.java @@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.postgres.core; import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.postgres.entity.ModelMngEntity; import com.kamco.cd.kamcoback.postgres.repository.model.ModelMngRepository; +import jakarta.persistence.EntityNotFoundException; import java.time.LocalDate; import java.time.ZonedDateTime; import java.util.UUID; @@ -82,4 +83,12 @@ public class ModelMngCoreService { // ModelMngEntity entity = modelMngRepository.save(addEntity); // return entity.getMetricUid(); } + + public ModelMngDto.Basic findByModelUuid(Long id) { + ModelMngEntity entity = + modelMngRepository + .findByModelId(id) + .orElseThrow(() -> new EntityNotFoundException("모델 정보가 없습니다.")); + return entity.toDto(); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java index b219ce4a..516a963e 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/ModelMngEntity.java @@ -1,5 +1,6 @@ package com.kamco.cd.kamcoback.postgres.entity; +import com.kamco.cd.kamcoback.model.dto.ModelMngDto; import com.kamco.cd.kamcoback.postgres.CommonDateEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -90,8 +91,32 @@ public class ModelMngEntity extends CommonDateEntity { @Column(name = "priority") private Double priority; - public void deleted() { this.deleted = true; } + + public ModelMngDto.Basic toDto() { + return new ModelMngDto.Basic( + this.modelUid, + this.modelVer, + this.createCompleteDttm, + this.recentUseDttm, + this.deleted, + this.getCreatedDate(), + this.createdUid, + this.getModifiedDate(), + this.updatedUid, + this.modelType, + this.filePath, + this.fileName, + this.cdModelPath, + this.cdModelFileName, + this.cdModelConfigPath, + this.cdModelConfigFileName, + this.clsModelPath, + this.clsModelFileName, + this.clsModelVersion, + this.priority, + this.memo); + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java index a48675e5..bba1c4fe 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryCustom.java @@ -25,4 +25,6 @@ public interface ModelMngRepositoryCustom { void deleteByModelUuid(UUID uuid); void insertModelResultMetric(ModelMngDto.ModelMetricAddReq addReq); + + Optional findByModelId(Long id); } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java index 6da27b60..96ff3a52 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/repository/model/ModelMngRepositoryImpl.java @@ -89,8 +89,7 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport modelMngEntity.clsModelPath, modelMngEntity.clsModelFileName, modelMngEntity.clsModelVersion, - modelMngEntity.priority - )) + modelMngEntity.priority)) .from(modelMngEntity) .innerJoin(modelResultMetricEntity) .on(modelMngEntity.modelUid.eq(modelResultMetricEntity.modelUid)) @@ -230,4 +229,10 @@ public class ModelMngRepositoryImpl extends QuerydslRepositorySupport addReq.getIou()) .execute(); } + + @Override + public Optional findByModelId(Long id) { + return Optional.ofNullable( + queryFactory.selectFrom(modelMngEntity).where(modelMngEntity.modelUid.eq(id)).fetchOne()); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 790a1c95..9c4b17d3 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -79,3 +79,21 @@ mapsheet: shp: baseurl: /app/tmp/detect/result + + +file: + #sync-root-dir: D:/app/original-images/ + sync-root-dir: /app/original-images/ + sync-tmp-dir: ${file.sync-root-dir}/tmp + sync-file-extention: tfw,tif + + #dataset-dir: D:/app/dataset/ + dataset-dir: /app/dataset/ + dataset-tmp-dir: ${file.dataset-dir}tmp/ + + #model-dir: D:/app/model/ + model-dir: /app/model/ + model-tmp-dir: ${file.model-dir}tmp/ + +inference: + url: http://10.100.0.11:8000/jobs diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 37250f1e..e5bab69f 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -4,7 +4,7 @@ spring: on-profile: local jpa: - show-sql: true + show-sql: false hibernate: ddl-auto: validate # 로컬만 완화(시킬려면 update으로 변경) properties: @@ -54,8 +54,32 @@ springdoc: swagger-ui: persist-authorization: true # 스웨거 새로고침해도 토큰 유지, 로컬스토리지에 저장 +logging: + level: + org.hibernate.SQL: debug + org.hibernate.orm.jdbc.bind: trace + mapsheet: upload: skipGdalValidation: true shp: baseurl: /Users/bokmin/detect/result + + + +file: + #sync-root-dir: D:/app/original-images/ + sync-root-dir: /Users/bokmin/kamco_file/geojson/ + sync-tmp-dir: ${file.sync-root-dir}/tmp + sync-file-extention: tfw,tif + + #dataset-dir: D:/app/dataset/ + dataset-dir: /Users/bokmin/kamco_file/dataset/ + dataset-tmp-dir: ${file.dataset-dir}tmp/ + + #model-dir: D:/app/model/ + model-dir: /Users/bokmin/kamco_file/model/ + model-tmp-dir: ${file.model-dir}tmp/ + +inference: + url: http://10.100.0.11:8000/jobs diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 5a23ca0e..de585024 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -40,3 +40,22 @@ mapsheet: shp: baseurl: /app/detect/result + + +file: + #sync-root-dir: D:/app/original-images/ + sync-root-dir: /app/original-images/ + sync-tmp-dir: ${file.sync-root-dir}/tmp + sync-file-extention: tfw,tif + + #dataset-dir: D:/app/dataset/ + dataset-dir: /app/dataset/ + dataset-tmp-dir: ${file.dataset-dir}tmp/ + + #model-dir: D:/app/model/ + model-dir: /app/model/ + model-tmp-dir: ${file.model-dir}tmp/ + +inference: + url: http://10.100.0.11:8000/jobs + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f03cbd99..6b64cf0e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -64,17 +64,3 @@ management: include: - "health" - -file: - #sync-root-dir: D:/app/original-images/ - sync-root-dir: /app/original-images/ - sync-tmp-dir: ${file.sync-root-dir}/tmp - sync-file-extention: tfw,tif - - #dataset-dir: D:/app/dataset/ - dataset-dir: /app/dataset/ - dataset-tmp-dir: ${file.dataset-dir}tmp/ - - #model-dir: D:/app/model/ - model-dir: /app/model/ - model-tmp-dir: ${file.model-dir}tmp/