Merge remote-tracking branch 'origin/feat/infer_dev_260107' into feat/infer_dev_260107
This commit is contained in:
@@ -20,6 +20,10 @@ public enum DetectionClassification {
|
||||
TUMULUS("tumulus", "토분(무덤)", 120),
|
||||
WASTE("waste", "폐기물", 130),
|
||||
WATER("water", "물", 140),
|
||||
CONSTRUCTION("construction", "건설", 150),
|
||||
NDC("NDC", "미분류", 160),
|
||||
RICE("rice", "논", 170),
|
||||
WOOD("wood", "산림", 180),
|
||||
ETC("ETC", "기타", 200); // For 'etc' (miscellaneous/other)
|
||||
|
||||
private final String id;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.kamco.cd.kamcoback.common.service;
|
||||
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultsTestingDto;
|
||||
import com.kamco.cd.kamcoback.postgres.core.InferenceResultCoreService;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -17,28 +15,8 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class ExternalJarRunner {
|
||||
|
||||
private final InferenceResultCoreService inferenceResultCoreService;
|
||||
|
||||
public void run(String jarPath, String batchIds, String inferenceId, String mapIds) {
|
||||
|
||||
List<Long> batch = new ArrayList<>();
|
||||
batch.add(285L);
|
||||
batch.add(286L);
|
||||
batch.add(287L);
|
||||
List<InferenceResultsTestingDto.ShpDto> resultList =
|
||||
inferenceResultCoreService.getInferenceResults(batch);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
mapIds = sb.toString();
|
||||
for (InferenceResultsTestingDto.ShpDto dto : resultList) {
|
||||
if (dto.getMapId() == null) {
|
||||
continue;
|
||||
}
|
||||
if (!sb.isEmpty()) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("\"").append(dto.getMapId()).append("\"");
|
||||
}
|
||||
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
try {
|
||||
|
||||
@@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
@@ -45,7 +46,8 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
public boolean supports(
|
||||
MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
// ApiResponseDto를 반환하는 경우에만 적용
|
||||
return returnType.getParameterType().equals(ApiResponseDto.class);
|
||||
return returnType.getParameterType().equals(ApiResponseDto.class)
|
||||
|| returnType.getParameterType().equals(ResponseEntity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.kamco.cd.kamcoback.inference;
|
||||
|
||||
import com.kamco.cd.kamcoback.common.exception.CustomApiException;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||
@@ -20,11 +21,19 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -33,6 +42,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
@Tag(name = "추론관리", description = "추론관리 API")
|
||||
@RequestMapping("/api/inference")
|
||||
@@ -388,4 +398,47 @@ public class InferenceResultApiController {
|
||||
inferenceResultService.getInferenceGeomList(uuid, searchGeoReq);
|
||||
return ApiResponseDto.ok(geomList);
|
||||
}
|
||||
|
||||
@Operation(summary = "shp 파일 다운로드", description = "추론관리 분석결과 shp 파일 다운로드")
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "shp zip파일 다운로드",
|
||||
content =
|
||||
@Content(
|
||||
mediaType = "application/octet-stream",
|
||||
schema = @Schema(type = "string", format = "binary"))),
|
||||
@ApiResponse(responseCode = "404", description = "파일 없음", content = @Content),
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@GetMapping(value = "/download/{uuid}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public ResponseEntity<Resource> downloadZip(@PathVariable UUID uuid) throws IOException {
|
||||
|
||||
String path;
|
||||
try {
|
||||
path = String.valueOf(inferenceResultService.shpDownloadPath(uuid));
|
||||
} catch (CustomApiException e) {
|
||||
// 데이터 없음 등 404
|
||||
return ResponseEntity.status(e.getStatus()).build();
|
||||
}
|
||||
|
||||
Path zipPath = Path.of(path);
|
||||
FileSystemResource resource = new FileSystemResource(zipPath);
|
||||
|
||||
if (!resource.exists() || !resource.isReadable()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
String filename = zipPath.getFileName().toString();
|
||||
String encodedFilename = UriUtils.encode(filename, StandardCharsets.UTF_8);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.header(
|
||||
HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + filename + "\"; filename*=UTF-8''" + encodedFilename)
|
||||
.contentLength(resource.contentLength())
|
||||
.body((Resource) resource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,4 +622,11 @@ public class InferenceResultDto {
|
||||
private Integer completedJobs;
|
||||
private Integer failedJobs;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class InferenceLearnDto {
|
||||
|
||||
private String uid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/** AI API 추론 실행 DTO */
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.DetectOption;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceLearnDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheetNumDto;
|
||||
@@ -32,6 +33,7 @@ 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.nio.file.Path;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -70,6 +72,9 @@ public class InferenceResultService {
|
||||
@Value("${inference.batch-url}")
|
||||
private String batchUrl;
|
||||
|
||||
@Value("${file.dataset-dir}")
|
||||
private String datasetDir;
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String profile;
|
||||
|
||||
@@ -536,4 +541,17 @@ public class InferenceResultService {
|
||||
Long learnId = inferenceResultCoreService.getInferenceLearnIdByUuid(dto.getUuid());
|
||||
inferenceResultCoreService.upsertGeomData(learnId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 추론결과 shp zip 파일 다운로드 경로 생성
|
||||
*
|
||||
* @param uuid
|
||||
* @return
|
||||
*/
|
||||
public Path shpDownloadPath(UUID uuid) {
|
||||
InferenceLearnDto dto = inferenceResultCoreService.getInferenceUid(uuid);
|
||||
String uid = dto.getUid();
|
||||
|
||||
return Path.of(datasetDir).resolve(uid).resolve("merge").resolve(uid + ".zip");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.MapSheet;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.SearchGeoReq;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceProgressDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceLearnDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceServerStatusDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
|
||||
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.ResultList;
|
||||
@@ -461,4 +462,20 @@ public class InferenceResultCoreService {
|
||||
inferenceResultsTetingRepository.getInferenceResultList(batchIds);
|
||||
return list.stream().map(InferenceResultsTestingDto.ShpDto::fromEntity).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* uid 조회
|
||||
*
|
||||
* @param uuid
|
||||
* @return
|
||||
*/
|
||||
public InferenceLearnDto getInferenceUid(UUID uuid) {
|
||||
MapSheetLearnEntity entity =
|
||||
inferenceResultRepository
|
||||
.getInferenceUid(uuid)
|
||||
.orElseThrow(() -> new CustomApiException("NOT_FOUND_DATA", HttpStatus.NOT_FOUND));
|
||||
InferenceLearnDto dto = new InferenceLearnDto();
|
||||
dto.setUid(entity.getUid());
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.kamco.cd.kamcoback.postgres.core;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.repository.scheduler.TrainingDataReviewJobRepository;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.InspectorPendingDto;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.Tasks;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TrainingDataReviewJobCoreService {
|
||||
|
||||
private final TrainingDataReviewJobRepository trainingDataReviewJobRepository;
|
||||
|
||||
public List<Tasks> findCompletedYesterdayUnassigned() {
|
||||
return trainingDataReviewJobRepository.findCompletedYesterdayUnassigned();
|
||||
}
|
||||
|
||||
public void assignReviewer(UUID assignmentUid, String reviewerId) {
|
||||
trainingDataReviewJobRepository.assignReviewer(assignmentUid, reviewerId);
|
||||
}
|
||||
|
||||
public void assignReviewerBatch(List<UUID> assignmentUids, String reviewerId) {
|
||||
trainingDataReviewJobRepository.assignReviewerBatch(assignmentUids, reviewerId);
|
||||
}
|
||||
|
||||
public Tasks findAssignmentTask(String assignmentUid) {
|
||||
return trainingDataReviewJobRepository.findAssignmentTask(assignmentUid);
|
||||
}
|
||||
|
||||
public List<InspectorPendingDto> findInspectorPendingByRound(Long analUid) {
|
||||
return trainingDataReviewJobRepository.findInspectorPendingByRound(analUid);
|
||||
}
|
||||
|
||||
public void lockInspectors(Long analUid, List<String> reviewerIds) {
|
||||
trainingDataReviewJobRepository.lockInspectors(analUid, reviewerIds);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface InferenceResultRepositoryCustom {
|
||||
@@ -27,4 +29,6 @@ public interface InferenceResultRepositoryCustom {
|
||||
List<MapSheetAnalDataInferenceGeomEntity> findGeomEntitiesByDataUid(Long dataUid, int limit);
|
||||
|
||||
Long getInferenceLearnIdByUuid(UUID uuid);
|
||||
|
||||
public Optional<MapSheetLearnEntity> getInferenceUid(UUID uuid);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnEntity.mapSheetLearnEntity;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataInferenceGeomEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity;
|
||||
@@ -10,6 +11,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@@ -468,4 +470,14 @@ public class InferenceResultRepositoryImpl implements InferenceResultRepositoryC
|
||||
.where(mapSheetLearnEntity.uuid.eq(uuid))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MapSheetLearnEntity> getInferenceUid(UUID uuid) {
|
||||
return Optional.ofNullable(
|
||||
queryFactory
|
||||
.select(mapSheetLearnEntity)
|
||||
.from(mapSheetLearnEntity)
|
||||
.where(mapSheetLearnEntity.uuid.eq(uuid))
|
||||
.fetchOne());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.postgres.repository.Inference;
|
||||
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QGpuMetricEntity.gpuMetricEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity;
|
||||
@@ -339,7 +340,7 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
.select(
|
||||
Projections.constructor(
|
||||
Dashboard.class,
|
||||
mapSheetAnalSttcEntity.id.classAfterCd,
|
||||
mapSheetAnalSttcEntity.id.classAfterCd.toUpperCase(),
|
||||
mapSheetAnalSttcEntity.classAfterCnt.sum()))
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.innerJoin(mapSheetAnalSttcEntity)
|
||||
@@ -419,13 +420,10 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
// mapSheetAnalDataInferenceGeomEntity.geomCenter)
|
||||
))
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.join(mapSheetAnalDataInferenceEntity)
|
||||
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
||||
.join(mapSheetAnalDataInferenceGeomEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(
|
||||
mapSheetAnalInferenceEntity.compareYyyy),
|
||||
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(
|
||||
mapSheetAnalInferenceEntity.targetYyyy),
|
||||
mapSheetAnalDataInferenceGeomEntity.stage.eq(mapSheetAnalInferenceEntity.stage))
|
||||
.on(mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id))
|
||||
.join(mapInkx5kEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceGeomEntity.mapSheetNum.eq(
|
||||
@@ -440,13 +438,10 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
|
||||
queryFactory
|
||||
.select(mapSheetAnalDataInferenceGeomEntity.geoUid)
|
||||
.from(mapSheetAnalInferenceEntity)
|
||||
.join(mapSheetAnalDataInferenceEntity)
|
||||
.on(mapSheetAnalDataInferenceEntity.analUid.eq(mapSheetAnalInferenceEntity.id))
|
||||
.join(mapSheetAnalDataInferenceGeomEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(
|
||||
mapSheetAnalInferenceEntity.compareYyyy),
|
||||
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(
|
||||
mapSheetAnalInferenceEntity.targetYyyy),
|
||||
mapSheetAnalDataInferenceGeomEntity.stage.eq(mapSheetAnalInferenceEntity.stage))
|
||||
.on(mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id))
|
||||
.join(mapInkx5kEntity)
|
||||
.on(
|
||||
mapSheetAnalDataInferenceGeomEntity.mapSheetNum.eq(
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.scheduler;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.entity.LabelingInspectorEntity;
|
||||
import jakarta.persistence.LockModeType;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
public interface TrainingDataReviewJobRepository
|
||||
extends JpaRepository<LabelingInspectorEntity, UUID>, TrainingDataReviewJobRepositoryCustom {
|
||||
|
||||
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||
@Query(
|
||||
"""
|
||||
select r
|
||||
from LabelingInspectorEntity r
|
||||
where r.analUid = :analUid
|
||||
and r.inspectorUid in :inspectorUids
|
||||
""")
|
||||
List<LabelingInspectorEntity> lockInspectors(Long analUid, List<String> inspectorUids);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.scheduler;
|
||||
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.InspectorPendingDto;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.Tasks;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TrainingDataReviewJobRepositoryCustom {
|
||||
|
||||
List<Tasks> findCompletedYesterdayUnassigned();
|
||||
|
||||
List<InspectorPendingDto> findInspectorPendingByRound(Long analUid);
|
||||
|
||||
void assignReviewer(UUID assignmentUid, String reviewerId);
|
||||
|
||||
void assignReviewerBatch(List<UUID> assignmentUids, String reviewerId);
|
||||
|
||||
Tasks findAssignmentTask(String assignmentUid);
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.kamco.cd.kamcoback.postgres.repository.scheduler;
|
||||
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.labelingAssignmentEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QLabelingInspectorEntity.labelingInspectorEntity;
|
||||
|
||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.InspectState;
|
||||
import com.kamco.cd.kamcoback.label.dto.LabelAllocateDto.LabelState;
|
||||
import com.kamco.cd.kamcoback.postgres.entity.LabelingAssignmentEntity;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.InspectorPendingDto;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.Tasks;
|
||||
import com.querydsl.core.types.Projections;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
|
||||
|
||||
public class TrainingDataReviewJobRepositoryImpl extends QuerydslRepositorySupport
|
||||
implements TrainingDataReviewJobRepositoryCustom {
|
||||
|
||||
private final JPAQueryFactory queryFactory;
|
||||
private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)");
|
||||
|
||||
public TrainingDataReviewJobRepositoryImpl(JPAQueryFactory queryFactory) {
|
||||
super(LabelingAssignmentEntity.class);
|
||||
this.queryFactory = queryFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tasks> findCompletedYesterdayUnassigned() {
|
||||
ZoneId zone = ZoneId.of("Asia/Seoul");
|
||||
ZonedDateTime todayStart = ZonedDateTime.now(zone).toLocalDate().atStartOfDay(zone);
|
||||
ZonedDateTime yesterdayStart = todayStart.minusDays(1);
|
||||
|
||||
BooleanExpression isYesterday =
|
||||
labelingAssignmentEntity
|
||||
.workStatDttm
|
||||
.goe(yesterdayStart)
|
||||
.and(labelingAssignmentEntity.workStatDttm.lt(todayStart));
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
Tasks.class,
|
||||
labelingAssignmentEntity.assignmentUid,
|
||||
labelingAssignmentEntity.inferenceGeomUid,
|
||||
labelingAssignmentEntity.analUid))
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(
|
||||
labelingAssignmentEntity.workState.in(LabelState.SKIP.getId(), LabelState.DONE.getId()),
|
||||
labelingAssignmentEntity.inspectorUid.isNull(),
|
||||
isYesterday)
|
||||
.orderBy(
|
||||
labelingAssignmentEntity.analUid.asc(),
|
||||
labelingAssignmentEntity.assignGroupId.asc(),
|
||||
labelingAssignmentEntity.inferenceGeomUid.asc())
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 해당 회차에 라벨링 할당받은 검수자별 완료 건수 count(), 완료한 게 적은 순으로 해야 일이 한 사람에게 몰리지 않음
|
||||
*
|
||||
* @param analUid
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<InspectorPendingDto> findInspectorPendingByRound(Long analUid) {
|
||||
return queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
InspectorPendingDto.class,
|
||||
labelingInspectorEntity.inspectorUid,
|
||||
labelingAssignmentEntity.assignmentUid.count()))
|
||||
.from(labelingInspectorEntity)
|
||||
.leftJoin(labelingAssignmentEntity)
|
||||
.on(
|
||||
labelingInspectorEntity.inspectorUid.eq(labelingAssignmentEntity.inspectorUid),
|
||||
labelingAssignmentEntity.inspectState.in(
|
||||
InspectState.EXCEPT.getId(), InspectState.COMPLETE.getId()))
|
||||
.where(labelingInspectorEntity.analUid.eq(analUid))
|
||||
.groupBy(labelingInspectorEntity.inspectorUid)
|
||||
.orderBy(labelingAssignmentEntity.assignmentUid.count().asc())
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 실시간 분배용 1건 update
|
||||
*
|
||||
* @param assignmentUid
|
||||
* @param reviewerId
|
||||
*/
|
||||
@Override
|
||||
public void assignReviewer(UUID assignmentUid, String reviewerId) {
|
||||
queryFactory
|
||||
.update(labelingAssignmentEntity)
|
||||
.set(labelingAssignmentEntity.inspectorUid, reviewerId)
|
||||
.set(labelingAssignmentEntity.inspectState, InspectState.UNCONFIRM.getId())
|
||||
.where(labelingAssignmentEntity.assignmentUid.eq(assignmentUid))
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 배치용 여러 건 update
|
||||
*
|
||||
* @param assignmentUids
|
||||
* @param reviewerId
|
||||
*/
|
||||
@Override
|
||||
public void assignReviewerBatch(List<UUID> assignmentUids, String reviewerId) {
|
||||
queryFactory
|
||||
.update(labelingAssignmentEntity)
|
||||
.set(labelingAssignmentEntity.inspectorUid, reviewerId)
|
||||
.set(labelingAssignmentEntity.inspectState, InspectState.UNCONFIRM.getId())
|
||||
.where(labelingAssignmentEntity.assignmentUid.in(assignmentUids))
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tasks findAssignmentTask(String assignmentUid) {
|
||||
return queryFactory
|
||||
.select(
|
||||
Projections.constructor(
|
||||
Tasks.class,
|
||||
labelingAssignmentEntity.assignmentUid,
|
||||
labelingAssignmentEntity.inferenceGeomUid,
|
||||
labelingAssignmentEntity.analUid))
|
||||
.from(labelingAssignmentEntity)
|
||||
.where(labelingAssignmentEntity.assignmentUid.eq(UUID.fromString(assignmentUid)))
|
||||
.fetchOne();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import static com.kamco.cd.kamcoback.postgres.entity.QLabelingAssignmentEntity.l
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnDataGeomEntity.mapSheetLearnDataGeomEntity;
|
||||
import static com.kamco.cd.kamcoback.postgres.entity.QMemberEntity.memberEntity;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -442,6 +443,26 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
|
||||
// COG URL 조회 실패 시 빈 문자열 유지
|
||||
}
|
||||
|
||||
// 4-1. 라벨러 성명 조회 (worker_uid로 tb_member의 name 조회)
|
||||
String workerName = "";
|
||||
try {
|
||||
if (assignment.toDto().getWorkerUid() != null
|
||||
&& !assignment.toDto().getWorkerUid().isEmpty()) {
|
||||
workerName =
|
||||
queryFactory
|
||||
.select(memberEntity.name)
|
||||
.from(memberEntity)
|
||||
.where(memberEntity.userId.eq(assignment.toDto().getWorkerUid()))
|
||||
.fetchFirst();
|
||||
if (workerName == null) {
|
||||
workerName = "";
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Worker name retrieval error: " + e.getMessage());
|
||||
// 라벨러 성명 조회 실패 시 빈 문자열 유지
|
||||
}
|
||||
|
||||
// 5. DTO 생성
|
||||
var changeDetectionInfo =
|
||||
ChangeDetectionInfo.builder()
|
||||
@@ -492,6 +513,7 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
|
||||
mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() != null
|
||||
? mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum()
|
||||
: 0L)
|
||||
.workerName(workerName)
|
||||
.build();
|
||||
|
||||
var inspectionResultInfo =
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.kamco.cd.kamcoback.scheduler.dto;
|
||||
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
public class TrainingDataReviewJobDto {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Tasks {
|
||||
|
||||
private UUID assignmentUid;
|
||||
private Long inferenceUid;
|
||||
private Long analUid;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class InspectorPendingDto {
|
||||
|
||||
String inspectorUid;
|
||||
Long pendingCount;
|
||||
}
|
||||
}
|
||||
@@ -237,8 +237,10 @@ public class MapSheetInferenceJobService {
|
||||
String mapIds = sb.toString();
|
||||
String batchId = sheet.getM1BatchId() + "," + sheet.getM2BatchId() + "," + sheet.getM3BatchId();
|
||||
|
||||
// uid 기준 도엽별 shp, geojson 파일 생성
|
||||
externalJarRunner.run(jarPath, batchId, inferenceId, mapIds);
|
||||
|
||||
// uid 기준 merge shp, geojson 파일 생성
|
||||
externalJarRunner.run(jarPath, batchId, inferenceId, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.kamco.cd.kamcoback.scheduler.service;
|
||||
|
||||
import com.kamco.cd.kamcoback.postgres.core.TrainingDataReviewJobCoreService;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.InspectorPendingDto;
|
||||
import com.kamco.cd.kamcoback.scheduler.dto.TrainingDataReviewJobDto.Tasks;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Log4j2
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TrainingDataReviewJobService {
|
||||
|
||||
private final TrainingDataReviewJobCoreService trainingDataReviewJobCoreService;
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String profile;
|
||||
|
||||
private boolean isLocalProfile() {
|
||||
return "local".equalsIgnoreCase(profile);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Scheduled(cron = "0 0 0 * * *")
|
||||
public void assignReviewerYesterdayLabelComplete() {
|
||||
|
||||
if (isLocalProfile()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Tasks> tasks = trainingDataReviewJobCoreService.findCompletedYesterdayUnassigned();
|
||||
|
||||
if (tasks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 회차별로 그룹핑
|
||||
Map<Long, List<Tasks>> taskByRound =
|
||||
tasks.stream().collect(Collectors.groupingBy(Tasks::getAnalUid));
|
||||
|
||||
// 회차별 분배
|
||||
for (Map.Entry<Long, List<Tasks>> entry : taskByRound.entrySet()) {
|
||||
Long analUid = entry.getKey();
|
||||
List<Tasks> analTasks = entry.getValue();
|
||||
|
||||
// pending 계산
|
||||
List<InspectorPendingDto> pendings =
|
||||
trainingDataReviewJobCoreService.findInspectorPendingByRound(analUid);
|
||||
|
||||
if (pendings.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> reviewerIds =
|
||||
pendings.stream().map(InspectorPendingDto::getInspectorUid).toList();
|
||||
|
||||
// Lock 걸릴 수 있기 때문에 엔티티 조회하는 Repository 에서 구현
|
||||
trainingDataReviewJobCoreService.lockInspectors(analUid, reviewerIds);
|
||||
|
||||
// 균등 분배
|
||||
Map<String, List<Tasks>> assignMap = distributeByLeastPending(analTasks, reviewerIds);
|
||||
|
||||
// reviewer별 batch update
|
||||
assignMap.forEach(
|
||||
(reviewerId, assignedTasks) -> {
|
||||
if (assignedTasks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<UUID> assignmentUids =
|
||||
assignedTasks.stream().map(Tasks::getAssignmentUid).toList();
|
||||
|
||||
trainingDataReviewJobCoreService.assignReviewerBatch(assignmentUids, reviewerId);
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("배치 처리 중 예외", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<Tasks>> distributeByLeastPending(
|
||||
List<Tasks> tasks, List<String> reviewerIds) {
|
||||
Map<String, List<Tasks>> result = new LinkedHashMap<>();
|
||||
|
||||
// 순서 유지 중요 (ASC 정렬된 상태)
|
||||
for (String reviewerId : reviewerIds) {
|
||||
result.put(reviewerId, new ArrayList<>());
|
||||
}
|
||||
|
||||
int reviewerCount = reviewerIds.size();
|
||||
|
||||
for (int i = 0; i < tasks.size(); i++) {
|
||||
String reviewerId = reviewerIds.get(i % reviewerCount);
|
||||
result.get(reviewerId).add(tasks.get(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 라벨러 완료,SKIP 시 호출
|
||||
@Transactional
|
||||
public void assignRealtime(String assignmentUid) {
|
||||
Tasks task = trainingDataReviewJobCoreService.findAssignmentTask(assignmentUid);
|
||||
Long analUid = task.getAnalUid();
|
||||
|
||||
// pending 계산
|
||||
List<InspectorPendingDto> pendings =
|
||||
trainingDataReviewJobCoreService.findInspectorPendingByRound(analUid);
|
||||
|
||||
if (pendings.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> order = pendings.stream().map(InspectorPendingDto::getInspectorUid).toList();
|
||||
|
||||
trainingDataReviewJobCoreService.lockInspectors(analUid, order);
|
||||
|
||||
trainingDataReviewJobCoreService.assignReviewer(task.getAssignmentUid(), order.getFirst());
|
||||
}
|
||||
}
|
||||
@@ -88,9 +88,9 @@ public class TrainingDataLabelApiController {
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PostMapping
|
||||
public ApiResponseDto<ResponseObj> saveLabelingFeature(
|
||||
public ApiResponseDto<String> saveLabelingFeature(
|
||||
@RequestBody TrainingDataLabelDto.LabelFeatureRequest request) {
|
||||
return ApiResponseDto.okObject(trainingDataLabelService.saveLabelingFeature(request));
|
||||
return ApiResponseDto.ok(trainingDataLabelService.saveLabelingFeature(request));
|
||||
}
|
||||
|
||||
@Operation(summary = "작업 통계 조회", description = "라벨러의 작업 현황 통계를 조회합니다. (전체/미작업/Today 건수)")
|
||||
@@ -376,10 +376,29 @@ public class TrainingDataLabelApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.663, 34.588],
|
||||
[126.662, 34.587],
|
||||
[126.664, 34.589],
|
||||
[126.663, 34.588]
|
||||
[255968.87499999875, 522096.0392135622],
|
||||
[255969.3749999955, 522097.7892135601],
|
||||
[255973.8750000003, 522103.53921356186],
|
||||
[255976.62499999997, 522108.53921356145],
|
||||
[255978.9607864372, 522110.87500000006],
|
||||
[255980.7107864374, 522111.624999999],
|
||||
[255982.53921356448, 522111.6250000003],
|
||||
[255988.37499999587, 522109.87499999726],
|
||||
[255988.37499999927, 522108.28921356244],
|
||||
[255990.12499999776, 522106.5392135628],
|
||||
[255990.87499999846, 522105.039213567],
|
||||
[255990.87500000012, 522102.4607864364],
|
||||
[255990.12499999718, 522100.4607864384],
|
||||
[255988.37499999863, 522097.46078643657],
|
||||
[255988.37499999968, 522096.46078643645],
|
||||
[255983.28921356171, 522092.8749999984],
|
||||
[255979.5392135627, 522088.37499999907],
|
||||
[255978.53921355822, 522087.8750000016],
|
||||
[255974.46078643817, 522087.874999998],
|
||||
[255971.21078643805, 522088.87499999977],
|
||||
[255969.87500000134, 522090.21078643604],
|
||||
[255968.87499999907, 522092.21078643575],
|
||||
[255968.87499999875, 522096.0392135622]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -408,10 +427,16 @@ public class TrainingDataLabelApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.663, 34.588],
|
||||
[126.662, 34.587],
|
||||
[126.664, 34.589],
|
||||
[126.663, 34.588]
|
||||
[168526.71078643727, 544547.3749999998],
|
||||
[168527.71078643794, 544548.3749999991],
|
||||
[168530.28921356675, 544548.6249999998],
|
||||
[168538.53921356046, 544547.1250000003],
|
||||
[168547.28921356154, 544547.374999999],
|
||||
[168549.53921357248, 544545.1250000008],
|
||||
[168526.9607864362, 544544.6249999998],
|
||||
[168525.87500000178, 544545.710786436],
|
||||
[168525.87499999133, 544547.3749999998],
|
||||
[168526.71078643727, 544547.3749999998]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -426,10 +451,22 @@ public class TrainingDataLabelApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.665, 34.590],
|
||||
[126.664, 34.589],
|
||||
[126.666, 34.591],
|
||||
[126.665, 34.590]
|
||||
[321550.124999999, 399476.9607864386],
|
||||
[321550.12500000146, 399480.53921356204],
|
||||
[321551.96078643796, 399482.37499999895],
|
||||
[321553.46078643616, 399483.12499999907],
|
||||
[321558.21078643785, 399484.62500000035],
|
||||
[321560.96078643884, 399486.1250000005],
|
||||
[321563.78921356366, 399486.1249999994],
|
||||
[321565.62500000204, 399484.28921355924],
|
||||
[321565.87499999726, 399479.7107864349],
|
||||
[321565.37500000506, 399478.71078644204],
|
||||
[321562.0392135627, 399476.12499999604],
|
||||
[321559.0392135677, 399474.62499999924],
|
||||
[321556.0392135648, 399473.6249999991],
|
||||
[321552.4607864374, 399473.6249999991],
|
||||
[321550.8750000004, 399474.96078643366],
|
||||
[321550.124999999, 399476.9607864386]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -444,10 +481,29 @@ public class TrainingDataLabelApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.667, 34.592],
|
||||
[126.666, 34.591],
|
||||
[126.668, 34.593],
|
||||
[126.667, 34.592]
|
||||
[386684.62499999895, 310943.28921356204],
|
||||
[386684.87499999773, 310944.7892135619],
|
||||
[386686.87500000314, 310949.03921356524],
|
||||
[386689.71078643756, 310952.37499999907],
|
||||
[386692.5392135586, 310952.6249999989],
|
||||
[386694.0392135624, 310951.87500000035],
|
||||
[386697.28921356064, 310951.87500000035],
|
||||
[386700.53921356215, 310948.62499999854],
|
||||
[386709.78921356826, 310946.37499999977],
|
||||
[386715.0392135615, 310942.87500000285],
|
||||
[386717.8750000029, 310939.2892135617],
|
||||
[386718.3750000007, 310937.28921356343],
|
||||
[386718.124999998, 310933.71078643954],
|
||||
[386716.87500000326, 310931.4607864389],
|
||||
[386712.7892135609, 310927.12499999825],
|
||||
[386708.4607864385, 310927.124999999],
|
||||
[386699.2107864381, 310931.3749999989],
|
||||
[386694.9607864365, 310932.6249999988],
|
||||
[386692.21078644064, 310932.8750000003],
|
||||
[386686.4607864376, 310935.12499999994],
|
||||
[386685.3750000027, 310936.2107864344],
|
||||
[386684.3750000007, 310938.71078643826],
|
||||
[386684.62499999895, 310943.28921356204]
|
||||
]
|
||||
]
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.trainingdata;
|
||||
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj;
|
||||
import com.kamco.cd.kamcoback.scheduler.service.TrainingDataReviewJobService;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataReviewDto;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataReviewDto.ReviewGeometryInfo;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataReviewDto.ReviewListDto;
|
||||
@@ -31,6 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class TrainingDataReviewApiController {
|
||||
|
||||
private final TrainingDataReviewService trainingDataReviewService;
|
||||
private final TrainingDataReviewJobService trainingDataReviewJobService;
|
||||
|
||||
@Operation(summary = "목록 조회", description = "검수 할당 목록 조회")
|
||||
@ApiResponses(
|
||||
@@ -88,9 +90,9 @@ public class TrainingDataReviewApiController {
|
||||
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
|
||||
})
|
||||
@PostMapping
|
||||
public ApiResponseDto<ResponseObj> saveReviewFeature(
|
||||
public ApiResponseDto<String> saveReviewFeature(
|
||||
@RequestBody TrainingDataReviewDto.GeoFeatureRequest request) {
|
||||
return ApiResponseDto.okObject(trainingDataReviewService.saveReviewFeature(request));
|
||||
return ApiResponseDto.ok(trainingDataReviewService.saveReviewFeature(request));
|
||||
}
|
||||
|
||||
@Operation(summary = "작업 통계 조회", description = "검수자의 작업 현황 통계를 조회합니다. (전체/미작업/Today 건수)")
|
||||
@@ -376,10 +378,29 @@ public class TrainingDataReviewApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.663, 34.588],
|
||||
[126.662, 34.587],
|
||||
[126.664, 34.589],
|
||||
[126.663, 34.588]
|
||||
[255968.87499999875, 522096.0392135622],
|
||||
[255969.3749999955, 522097.7892135601],
|
||||
[255973.8750000003, 522103.53921356186],
|
||||
[255976.62499999997, 522108.53921356145],
|
||||
[255978.9607864372, 522110.87500000006],
|
||||
[255980.7107864374, 522111.624999999],
|
||||
[255982.53921356448, 522111.6250000003],
|
||||
[255988.37499999587, 522109.87499999726],
|
||||
[255988.37499999927, 522108.28921356244],
|
||||
[255990.12499999776, 522106.5392135628],
|
||||
[255990.87499999846, 522105.039213567],
|
||||
[255990.87500000012, 522102.4607864364],
|
||||
[255990.12499999718, 522100.4607864384],
|
||||
[255988.37499999863, 522097.46078643657],
|
||||
[255988.37499999968, 522096.46078643645],
|
||||
[255983.28921356171, 522092.8749999984],
|
||||
[255979.5392135627, 522088.37499999907],
|
||||
[255978.53921355822, 522087.8750000016],
|
||||
[255974.46078643817, 522087.874999998],
|
||||
[255971.21078643805, 522088.87499999977],
|
||||
[255969.87500000134, 522090.21078643604],
|
||||
[255968.87499999907, 522092.21078643575],
|
||||
[255968.87499999875, 522096.0392135622]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -408,10 +429,16 @@ public class TrainingDataReviewApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.663, 34.588],
|
||||
[126.662, 34.587],
|
||||
[126.664, 34.589],
|
||||
[126.663, 34.588]
|
||||
[168526.71078643727, 544547.3749999998],
|
||||
[168527.71078643794, 544548.3749999991],
|
||||
[168530.28921356675, 544548.6249999998],
|
||||
[168538.53921356046, 544547.1250000003],
|
||||
[168547.28921356154, 544547.374999999],
|
||||
[168549.53921357248, 544545.1250000008],
|
||||
[168526.9607864362, 544544.6249999998],
|
||||
[168525.87500000178, 544545.710786436],
|
||||
[168525.87499999133, 544547.3749999998],
|
||||
[168526.71078643727, 544547.3749999998]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -426,10 +453,22 @@ public class TrainingDataReviewApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.665, 34.590],
|
||||
[126.664, 34.589],
|
||||
[126.666, 34.591],
|
||||
[126.665, 34.590]
|
||||
[321550.124999999, 399476.9607864386],
|
||||
[321550.12500000146, 399480.53921356204],
|
||||
[321551.96078643796, 399482.37499999895],
|
||||
[321553.46078643616, 399483.12499999907],
|
||||
[321558.21078643785, 399484.62500000035],
|
||||
[321560.96078643884, 399486.1250000005],
|
||||
[321563.78921356366, 399486.1249999994],
|
||||
[321565.62500000204, 399484.28921355924],
|
||||
[321565.87499999726, 399479.7107864349],
|
||||
[321565.37500000506, 399478.71078644204],
|
||||
[321562.0392135627, 399476.12499999604],
|
||||
[321559.0392135677, 399474.62499999924],
|
||||
[321556.0392135648, 399473.6249999991],
|
||||
[321552.4607864374, 399473.6249999991],
|
||||
[321550.8750000004, 399474.96078643366],
|
||||
[321550.124999999, 399476.9607864386]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -444,10 +483,29 @@ public class TrainingDataReviewApiController {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[126.667, 34.592],
|
||||
[126.666, 34.591],
|
||||
[126.668, 34.593],
|
||||
[126.667, 34.592]
|
||||
[386684.62499999895, 310943.28921356204],
|
||||
[386684.87499999773, 310944.7892135619],
|
||||
[386686.87500000314, 310949.03921356524],
|
||||
[386689.71078643756, 310952.37499999907],
|
||||
[386692.5392135586, 310952.6249999989],
|
||||
[386694.0392135624, 310951.87500000035],
|
||||
[386697.28921356064, 310951.87500000035],
|
||||
[386700.53921356215, 310948.62499999854],
|
||||
[386709.78921356826, 310946.37499999977],
|
||||
[386715.0392135615, 310942.87500000285],
|
||||
[386717.8750000029, 310939.2892135617],
|
||||
[386718.3750000007, 310937.28921356343],
|
||||
[386718.124999998, 310933.71078643954],
|
||||
[386716.87500000326, 310931.4607864389],
|
||||
[386712.7892135609, 310927.12499999825],
|
||||
[386708.4607864385, 310927.124999999],
|
||||
[386699.2107864381, 310931.3749999989],
|
||||
[386694.9607864365, 310932.6249999988],
|
||||
[386692.21078644064, 310932.8750000003],
|
||||
[386686.4607864376, 310935.12499999994],
|
||||
[386685.3750000027, 310936.2107864344],
|
||||
[386684.3750000007, 310938.71078643826],
|
||||
[386684.62499999895, 310943.28921356204]
|
||||
]
|
||||
]
|
||||
},
|
||||
@@ -498,4 +556,11 @@ public class TrainingDataReviewApiController {
|
||||
return ApiResponseDto.ok(
|
||||
trainingDataReviewService.getCogImageUrl(mapSheetNum, beforeYear, afterYear));
|
||||
}
|
||||
|
||||
@Hidden
|
||||
@GetMapping("/run-schedule")
|
||||
public ApiResponseDto<Void> runTrainingReviewSchedule() {
|
||||
trainingDataReviewJobService.assignReviewerYesterdayLabelComplete();
|
||||
return ApiResponseDto.ok(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +340,9 @@ public class TrainingDataReviewDto {
|
||||
|
||||
@Schema(description = "도엽번호 (map_sheet_num)", example = "34602057")
|
||||
private Long mapSheetNum;
|
||||
|
||||
@Schema(description = "라벨러 성명 (기존 작업자)", example = "홍길동")
|
||||
private String workerName;
|
||||
}
|
||||
|
||||
@Schema(name = "ClassificationInfo", description = "분류정보")
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.trainingdata.service;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode;
|
||||
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj;
|
||||
import com.kamco.cd.kamcoback.postgres.core.TrainingDataLabelCoreService;
|
||||
import com.kamco.cd.kamcoback.scheduler.service.TrainingDataReviewJobService;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DefaultPaging;
|
||||
import com.kamco.cd.kamcoback.trainingdata.dto.TrainingDataLabelDto.DetailRes;
|
||||
@@ -22,9 +23,13 @@ import org.springframework.stereotype.Service;
|
||||
public class TrainingDataLabelService {
|
||||
|
||||
private final TrainingDataLabelCoreService trainingDataLabelCoreService;
|
||||
private final TrainingDataReviewJobService trainingDataReviewJobService;
|
||||
|
||||
public TrainingDataLabelService(TrainingDataLabelCoreService trainingDataLabelCoreService) {
|
||||
public TrainingDataLabelService(
|
||||
TrainingDataLabelCoreService trainingDataLabelCoreService,
|
||||
TrainingDataReviewJobService trainingDataReviewJobService) {
|
||||
this.trainingDataLabelCoreService = trainingDataLabelCoreService;
|
||||
this.trainingDataReviewJobService = trainingDataReviewJobService;
|
||||
}
|
||||
|
||||
public Page<LabelingListDto> findLabelingAssignedList(searchReq searchReq, String userId) {
|
||||
@@ -36,7 +41,7 @@ public class TrainingDataLabelService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ResponseObj saveLabelingFeature(LabelFeatureRequest request) {
|
||||
public String saveLabelingFeature(LabelFeatureRequest request) {
|
||||
String status = "";
|
||||
String assignmentUid = request.getAssignmentUid();
|
||||
Long inferenceGeomUid =
|
||||
@@ -52,7 +57,11 @@ public class TrainingDataLabelService {
|
||||
trainingDataLabelCoreService.updateLabelingPolygonClass(
|
||||
inferenceGeomUid, request.getGeometry(), request.getProperties(), status);
|
||||
}
|
||||
return new ResponseObj(ApiResponseCode.OK, "저장되었습니다.");
|
||||
|
||||
// 라벨링 완료하면 실시간 검수 할당 (1건)
|
||||
trainingDataReviewJobService.assignRealtime(assignmentUid);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,7 +36,7 @@ public class TrainingDataReviewService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ResponseObj saveReviewFeature(GeoFeatureRequest request) {
|
||||
public String saveReviewFeature(GeoFeatureRequest request) {
|
||||
String status = "";
|
||||
String operatorUid = request.getOperatorUid();
|
||||
Long inferenceGeomUid = trainingDataReviewCoreService.findReviewOperatorGeoUid(operatorUid);
|
||||
@@ -52,7 +52,7 @@ public class TrainingDataReviewService {
|
||||
trainingDataReviewCoreService.updateReviewPolygonClass(
|
||||
inferenceGeomUid, request.getGeometry(), request.getProperties(), status);
|
||||
}
|
||||
return new ResponseObj(ApiResponseCode.OK, "저장되었습니다.");
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,4 +100,4 @@ inference:
|
||||
url: http://10.100.0.11:8000/jobs
|
||||
batch-url: http://10.100.0.11:8000/batches
|
||||
geojson-dir: /kamco-nfs/requests/
|
||||
jar-path: jar/makeshp-1.0.0.jar
|
||||
jar-path: /kamco-nfs/dataset/makeshp-1.0.0.jar
|
||||
|
||||
Reference in New Issue
Block a user