Merge remote-tracking branch 'origin/feat/infer_dev_260107' into feat/infer_dev_260107

This commit is contained in:
2026-01-14 17:25:01 +09:00
15 changed files with 282 additions and 10566 deletions

View File

@@ -5,8 +5,10 @@ import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.InferenceBatchSheet;
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.InferenceServerStatusDto;
@@ -390,4 +392,12 @@ public class InferenceResultCoreService {
public AnalResultInfo getInferenceResultInfo(String uuid) {
return mapSheetLearnRepository.getInferenceResultInfo(uuid);
}
public List<Dashboard> getInferenceClassCountList(String uuid) {
return mapSheetLearnRepository.getInferenceClassCountList(uuid);
}
public Page<Geom> getInferenceGeomList(String uuid, SearchGeoReq searchGeoReq) {
return mapSheetLearnRepository.getInferenceGeomList(uuid, searchGeoReq);
}
}

View File

@@ -176,7 +176,8 @@ public class LabelAllocateCoreService {
return detail; // analUid 없으면 순위 0으로 반환
}
List<LabelerDetail> allInspectors = labelAllocateRepository.findAllInspectorsForRanking(analUid);
List<LabelerDetail> allInspectors =
labelAllocateRepository.findAllInspectorsForRanking(analUid);
// 3. 순위 계산 (DENSE_RANK 로직: 동점자는 같은 순위, 다음 순위는 연속)
Long lastCompleteCnt = null;

View File

@@ -1,6 +1,9 @@
package com.kamco.cd.kamcoback.postgres.repository.Inference;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
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.InferenceServerStatusDto;
@@ -30,4 +33,8 @@ public interface MapSheetLearnRepositoryCustom {
Integer getLearnStage(Integer compareYear, Integer targetYear);
AnalResultInfo getInferenceResultInfo(String uuid);
List<Dashboard> getInferenceClassCountList(String uuid);
Page<Geom> getInferenceGeomList(String uuid, SearchGeoReq searchGeoReq);
}

View File

@@ -1,24 +1,35 @@
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.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalInferenceEntity.mapSheetAnalInferenceEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalSttcEntity.mapSheetAnalSttcEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetLearnEntity.mapSheetLearnEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QSystemMetricEntity.systemMetricEntity;
import com.kamco.cd.kamcoback.common.utils.DateRange;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.AnalResultInfo;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Dashboard;
import com.kamco.cd.kamcoback.inference.dto.InferenceDetailDto.Geom;
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.InferenceServerStatusDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.InferenceStatusDetailDto;
import com.kamco.cd.kamcoback.model.service.ModelMngService;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalInferenceEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetLearnEntity;
import com.kamco.cd.kamcoback.postgres.entity.QModelMngEntity;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityNotFoundException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
@@ -308,4 +319,149 @@ public class MapSheetLearnRepositoryImpl implements MapSheetLearnRepositoryCusto
.where(mapSheetLearnEntity.uuid.eq(UUID.fromString(uuid)))
.fetchOne();
}
@Override
public List<Dashboard> getInferenceClassCountList(String uuid) {
// analUid로 분석 정보 조회
MapSheetAnalInferenceEntity analEntity =
queryFactory
.selectFrom(mapSheetAnalInferenceEntity)
.where(mapSheetAnalInferenceEntity.uuid.eq(UUID.fromString(uuid)))
.fetchOne();
if (Objects.isNull(analEntity)) {
throw new EntityNotFoundException("MapSheetAnalInferenceEntity not found for analUid: ");
}
return queryFactory
.select(
Projections.constructor(
Dashboard.class,
mapSheetAnalSttcEntity.id.classAfterCd,
mapSheetAnalSttcEntity.classAfterCnt.sum()))
.from(mapSheetAnalSttcEntity)
.where(mapSheetAnalSttcEntity.id.analUid.eq(analEntity.getId()))
.groupBy(mapSheetAnalSttcEntity.id.classAfterCd)
.orderBy(mapSheetAnalSttcEntity.id.classAfterCd.asc())
.fetch();
}
/**
* 분석결과 상세 목록
*
* @param searchGeoReq
* @return
*/
@Override
public Page<Geom> getInferenceGeomList(String uuid, SearchGeoReq searchGeoReq) {
Pageable pageable = searchGeoReq.toPageable();
BooleanBuilder builder = new BooleanBuilder();
// analUid로 분석 정보 조회
MapSheetAnalInferenceEntity analEntity =
queryFactory
.selectFrom(mapSheetAnalInferenceEntity)
.where(mapSheetAnalInferenceEntity.uuid.eq(UUID.fromString(uuid)))
.fetchOne();
if (Objects.isNull(analEntity)) {
throw new EntityNotFoundException("MapSheetAnalInferenceEntity not found for analUid: ");
}
// 추론결과 id
builder.and(mapSheetAnalInferenceEntity.id.eq(analEntity.getId()));
// 기준년도 분류
if (searchGeoReq.getTargetClass() != null && !searchGeoReq.getTargetClass().equals("")) {
builder.and(
mapSheetAnalDataInferenceGeomEntity
.classAfterCd
.toLowerCase()
.eq(searchGeoReq.getTargetClass().toLowerCase()));
}
// 비교년도 분류
if (searchGeoReq.getCompareClass() != null && !searchGeoReq.getCompareClass().equals("")) {
builder.and(
mapSheetAnalDataInferenceGeomEntity
.classBeforeCd
.toLowerCase()
.eq(searchGeoReq.getCompareClass().toLowerCase()));
}
// 분석도엽
if (searchGeoReq.getMapSheetNum() != null && !searchGeoReq.getMapSheetNum().isEmpty()) {
List<Long> mapSheetNum = searchGeoReq.getMapSheetNum();
builder.and(mapSheetAnalDataInferenceGeomEntity.mapSheetNum.in(mapSheetNum));
}
List<Geom> content =
queryFactory
.select(
Projections.constructor(
Geom.class,
mapSheetAnalDataInferenceGeomEntity.uuid,
mapSheetAnalDataInferenceGeomEntity.compareYyyy,
mapSheetAnalDataInferenceGeomEntity.targetYyyy,
mapSheetAnalDataInferenceGeomEntity.cdProb,
mapSheetAnalDataInferenceGeomEntity.classBeforeCd,
mapSheetAnalDataInferenceGeomEntity.classBeforeProb,
mapSheetAnalDataInferenceGeomEntity.classAfterCd,
mapSheetAnalDataInferenceGeomEntity.classAfterProb,
mapSheetAnalDataInferenceGeomEntity.mapSheetNum,
mapInkx5kEntity.mapidNm,
Expressions.stringTemplate(
"ST_AsGeoJSON({0})", mapSheetAnalDataInferenceGeomEntity.geom),
Expressions.stringTemplate(
"ST_AsGeoJSON({0})", mapSheetAnalDataInferenceGeomEntity.geomCenter)))
.from(mapSheetAnalInferenceEntity)
.join(mapSheetAnalDataInferenceGeomEntity)
.on(
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(
mapSheetAnalInferenceEntity.compareYyyy),
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(
mapSheetAnalInferenceEntity.targetYyyy),
mapSheetAnalDataInferenceGeomEntity.stage.eq(mapSheetAnalInferenceEntity.stage))
.join(mapInkx5kEntity)
.on(
mapSheetAnalDataInferenceGeomEntity
.mapSheetNum
.stringValue()
.eq(mapInkx5kEntity.mapidcdNo))
.where(builder)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
long total =
queryFactory
.select(mapSheetAnalDataInferenceGeomEntity.geoUid)
.from(mapSheetAnalInferenceEntity)
.join(mapSheetAnalDataInferenceGeomEntity)
.on(
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(
mapSheetAnalInferenceEntity.compareYyyy),
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(
mapSheetAnalInferenceEntity.targetYyyy),
mapSheetAnalDataInferenceGeomEntity.stage.eq(mapSheetAnalInferenceEntity.stage))
.from(mapSheetAnalInferenceEntity)
.join(mapSheetAnalDataInferenceGeomEntity)
.on(
mapSheetAnalDataInferenceGeomEntity.compareYyyy.eq(
mapSheetAnalInferenceEntity.compareYyyy),
mapSheetAnalDataInferenceGeomEntity.targetYyyy.eq(
mapSheetAnalInferenceEntity.targetYyyy),
mapSheetAnalDataInferenceGeomEntity.stage.eq(mapSheetAnalInferenceEntity.stage))
.join(mapInkx5kEntity)
.on(
mapSheetAnalDataInferenceGeomEntity
.mapSheetNum
.stringValue()
.eq(mapInkx5kEntity.mapidcdNo))
.where(builder)
.fetchCount();
return new PageImpl<>(content, pageable, total);
}
}

View File

@@ -68,14 +68,10 @@ public interface LabelAllocateRepositoryCustom {
LabelerDetail findLabelerDetail(String userId, String uuid);
/**
* 순위 계산용 - 특정 회차의 모든 라벨러 통계 조회
*/
/** 순위 계산용 - 특정 회차의 모든 라벨러 통계 조회 */
List<LabelerDetail> findAllLabelersForRanking(Long analUid);
/**
* UUID로 analUid 조회
*/
/** UUID로 analUid 조회 */
Long findAnalUidByUuid(String uuid);
Long findMapSheetAnalInferenceUid(Integer compareYyyy, Integer targetYyyy, Integer stage);
@@ -90,9 +86,7 @@ public interface LabelAllocateRepositoryCustom {
LabelerDetail findInspectorDetail(String userId, String uuid);
/**
* 순위 계산용 - 특정 회차의 모든 검수자 통계 조회
*/
/** 순위 계산용 - 특정 회차의 모든 검수자 통계 조회 */
List<LabelerDetail> findAllInspectorsForRanking(Long analUid);
MoveInfo moveAvailUserList(String userId, String uuid);

View File

@@ -848,9 +848,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.fetchOne();
}
/**
* 특정 회차의 모든 라벨러 통계 조회 (순위 계산용)
*/
/** 특정 회차의 모든 라벨러 통계 조회 (순위 계산용) */
public List<LabelerDetail> findAllLabelersForRanking(Long analUid) {
QMemberEntity worker = QMemberEntity.memberEntity;
@@ -898,9 +896,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.fetch();
}
/**
* UUID로 analUid 조회
*/
/** UUID로 analUid 조회 */
@Override
public Long findAnalUidByUuid(String uuid) {
return queryFactory
@@ -1355,9 +1351,9 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
inspector.userRole,
inspector.name,
inspector.employeeNo,
assignedCnt, // count (총 배정 건수)
completeCnt, // completeCnt (완료 건수)
skipCnt, // skipCnt (스킵 건수)
assignedCnt, // count (총 배정 건수)
completeCnt, // completeCnt (완료 건수)
skipCnt, // skipCnt (스킵 건수)
percent,
Expressions.constant(0), // 순위는 Service 레이어에서 계산
labelingAssignmentEntity.inspectStatDttm.min(),
@@ -1375,9 +1371,7 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.fetchOne();
}
/**
* 순위 계산용 - 특정 회차의 모든 검수자 통계 조회
*/
/** 순위 계산용 - 특정 회차의 모든 검수자 통계 조회 */
public List<LabelerDetail> findAllInspectorsForRanking(Long analUid) {
QMemberEntity inspector = QMemberEntity.memberEntity;
@@ -1403,7 +1397,8 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
.count();
Expression<Long> remainCnt =
Expressions.numberTemplate(Long.class, "({0} - {1} - {2})", assignedCnt, skipCnt, completeCnt);
Expressions.numberTemplate(
Long.class, "({0} - {1} - {2})", assignedCnt, skipCnt, completeCnt);
return queryFactory
.select(
@@ -1412,9 +1407,9 @@ public class LabelAllocateRepositoryImpl implements LabelAllocateRepositoryCusto
inspector.userRole,
inspector.name,
inspector.employeeNo,
assignedCnt, // count (총 배정 건수)
completeCnt, // completeCnt (완료 건수)
skipCnt, // skipCnt (스킵 건수)
assignedCnt, // count (총 배정 건수)
completeCnt, // completeCnt (완료 건수)
skipCnt, // skipCnt (스킵 건수)
Expressions.constant(0.0), // percent
Expressions.constant(0), // ranking
labelingAssignmentEntity.inspectStatDttm.min(),

View File

@@ -472,6 +472,10 @@ public class TrainingDataLabelRepositoryImpl extends QuerydslRepositorySupport
mapSheetAnalDataInferenceGeomEntityEntity.getPnu() != null
? mapSheetAnalDataInferenceGeomEntityEntity.getPnu()
: 0L)
.mapSheetNum(
mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() != null
? mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum()
: 0L)
.build();
var inspectionResultInfo =

View File

@@ -491,6 +491,10 @@ public class TrainingDataReviewRepositoryImpl extends QuerydslRepositorySupport
mapSheetAnalDataInferenceGeomEntityEntity.getPnu() != null
? mapSheetAnalDataInferenceGeomEntityEntity.getPnu()
: 0L)
.mapSheetNum(
mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum() != null
? mapSheetAnalDataInferenceGeomEntityEntity.getMapSheetNum()
: 0L)
.build();
var inspectionResultInfo =