화면 선발지수 수정 반영
This commit is contained in:
@@ -214,7 +214,7 @@ export class CowService {
|
||||
*
|
||||
* @param cows - 필터링된 개체 목록
|
||||
* @param traitConditions - 형질별 가중치 조건 배열
|
||||
* @returns 순위가 적용된 개체 목록
|
||||
* @returns 순위가 적용된 개체 목록 / 리스트에 전달 / 농가/보은군 차트 (farmBreedVal, regionBreedVal)
|
||||
* @example
|
||||
* traitConditions = [
|
||||
* { traitNm: '도체중', weight: 8 },
|
||||
@@ -253,7 +253,7 @@ export class CowService {
|
||||
// Step 2: 친자감별 확인 - 유효하지 않으면 분석 불가
|
||||
if (!latestRequest || !isValidGenomeAnalysis(latestRequest.chipSireName, latestRequest.chipDamName, cow.cowId)) {
|
||||
// 분석불가 사유 결정
|
||||
let unavailableReason = '미분석';
|
||||
let unavailableReason = '분석불가';
|
||||
if (latestRequest) {
|
||||
if (latestRequest.chipSireName !== '일치') {
|
||||
unavailableReason = '부 불일치';
|
||||
|
||||
@@ -92,6 +92,7 @@ interface TraitAverageDto {
|
||||
traitName: string; // 형질명
|
||||
category: string; // 카테고리
|
||||
avgEbv: number; // 평균 EBV (표준화 육종가)
|
||||
avgEpd: number; // 평균 EPD (육종가 원본값)
|
||||
count: number; // 데이터 개수
|
||||
}
|
||||
|
||||
@@ -1155,6 +1156,7 @@ export class GenomeService {
|
||||
const results = await qb
|
||||
.select('detail.traitName', 'traitName')
|
||||
.addSelect('AVG(detail.traitEbv)', 'avgEbv')
|
||||
.addSelect('AVG(detail.traitVal)', 'avgEpd') // 육종가(EPD) 평균 추가
|
||||
.addSelect('COUNT(*)', 'count')
|
||||
.groupBy('detail.traitName')
|
||||
.getRawMany();
|
||||
@@ -1164,6 +1166,7 @@ export class GenomeService {
|
||||
traitName: row.traitName,
|
||||
category: TRAIT_CATEGORY_MAP[row.traitName] || '기타',
|
||||
avgEbv: Math.round(parseFloat(row.avgEbv) * 100) / 100,
|
||||
avgEpd: Math.round(parseFloat(row.avgEpd || 0) * 100) / 100, // 육종가(EPD) 평균
|
||||
count: parseInt(row.count, 10),
|
||||
}));
|
||||
}
|
||||
@@ -1551,12 +1554,15 @@ export class GenomeService {
|
||||
async getTraitRank(cowId: string, traitName: string): Promise<{
|
||||
traitName: string;
|
||||
cowEbv: number | null;
|
||||
cowEpd: number | null; // 개체 육종가(EPD)
|
||||
farmRank: number | null;
|
||||
farmTotal: number;
|
||||
regionRank: number | null;
|
||||
regionTotal: number;
|
||||
farmAvgEbv: number | null;
|
||||
regionAvgEbv: number | null;
|
||||
farmAvgEpd: number | null; // 농가 평균 육종가(EPD)
|
||||
regionAvgEpd: number | null; // 보은군 평균 육종가(EPD)
|
||||
}> {
|
||||
// 1. 현재 개체의 의뢰 정보 조회
|
||||
const cow = await this.cowRepository.findOne({
|
||||
@@ -1567,12 +1573,15 @@ export class GenomeService {
|
||||
return {
|
||||
traitName,
|
||||
cowEbv: null,
|
||||
cowEpd: null,
|
||||
farmRank: null,
|
||||
farmTotal: 0,
|
||||
regionRank: null,
|
||||
regionTotal: 0,
|
||||
farmAvgEbv: null,
|
||||
regionAvgEbv: null,
|
||||
farmAvgEpd: null,
|
||||
regionAvgEpd: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1585,12 +1594,15 @@ export class GenomeService {
|
||||
return {
|
||||
traitName,
|
||||
cowEbv: null,
|
||||
cowEpd: null,
|
||||
farmRank: null,
|
||||
farmTotal: 0,
|
||||
regionRank: null,
|
||||
regionTotal: 0,
|
||||
farmAvgEbv: null,
|
||||
regionAvgEbv: null,
|
||||
farmAvgEpd: null,
|
||||
regionAvgEpd: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1602,8 +1614,8 @@ export class GenomeService {
|
||||
relations: ['cow', 'farm'],
|
||||
});
|
||||
|
||||
// 3. 각 개체별 해당 형질 EBV 수집
|
||||
const allScores: { cowId: string; ebv: number; farmNo: number | null }[] = [];
|
||||
// 3. 각 개체별 해당 형질 EBV, EPD 수집
|
||||
const allScores: { cowId: string; ebv: number; epd: number | null; farmNo: number | null }[] = [];
|
||||
|
||||
for (const request of allRequests) {
|
||||
if (!request.cow?.cowId) continue;
|
||||
@@ -1621,6 +1633,7 @@ export class GenomeService {
|
||||
allScores.push({
|
||||
cowId: request.cow.cowId,
|
||||
ebv: Number(traitDetail.traitEbv),
|
||||
epd: traitDetail.traitVal !== null ? Number(traitDetail.traitVal) : null, // 육종가(EPD)
|
||||
farmNo: request.fkFarmNo,
|
||||
});
|
||||
}
|
||||
@@ -1629,9 +1642,10 @@ export class GenomeService {
|
||||
// 4. EBV 기준 내림차순 정렬
|
||||
allScores.sort((a, b) => b.ebv - a.ebv);
|
||||
|
||||
// 5. 현재 개체의 EBV 찾기
|
||||
// 5. 현재 개체의 EBV, EPD 찾기
|
||||
const currentCowData = allScores.find(s => s.cowId === cowId);
|
||||
const cowEbv = currentCowData?.ebv ?? null;
|
||||
const cowEpd = currentCowData?.epd ?? null;
|
||||
|
||||
// 6. 보은군 전체 순위
|
||||
const regionRank = currentCowData
|
||||
@@ -1639,10 +1653,14 @@ export class GenomeService {
|
||||
: null;
|
||||
const regionTotal = allScores.length;
|
||||
|
||||
// 보은군 평균 EBV
|
||||
// 보은군 평균 EBV, EPD
|
||||
const regionAvgEbv = allScores.length > 0
|
||||
? Math.round((allScores.reduce((sum, s) => sum + s.ebv, 0) / allScores.length) * 100) / 100
|
||||
: null;
|
||||
const regionEpdValues = allScores.filter(s => s.epd !== null).map(s => s.epd as number);
|
||||
const regionAvgEpd = regionEpdValues.length > 0
|
||||
? Math.round((regionEpdValues.reduce((sum, v) => sum + v, 0) / regionEpdValues.length) * 100) / 100
|
||||
: null;
|
||||
|
||||
// 7. 농가 내 순위
|
||||
const farmScores = allScores.filter(s => s.farmNo === farmNo);
|
||||
@@ -1651,20 +1669,27 @@ export class GenomeService {
|
||||
: null;
|
||||
const farmTotal = farmScores.length;
|
||||
|
||||
// 농가 평균 EBV
|
||||
// 농가 평균 EBV, EPD
|
||||
const farmAvgEbv = farmScores.length > 0
|
||||
? Math.round((farmScores.reduce((sum, s) => sum + s.ebv, 0) / farmScores.length) * 100) / 100
|
||||
: null;
|
||||
const farmEpdValues = farmScores.filter(s => s.epd !== null).map(s => s.epd as number);
|
||||
const farmAvgEpd = farmEpdValues.length > 0
|
||||
? Math.round((farmEpdValues.reduce((sum, v) => sum + v, 0) / farmEpdValues.length) * 100) / 100
|
||||
: null;
|
||||
|
||||
return {
|
||||
traitName,
|
||||
cowEbv: cowEbv !== null ? Math.round(cowEbv * 100) / 100 : null,
|
||||
cowEpd: cowEpd !== null ? Math.round(cowEpd * 100) / 100 : null,
|
||||
farmRank: farmRank && farmRank > 0 ? farmRank : null,
|
||||
farmTotal,
|
||||
regionRank: regionRank && regionRank > 0 ? regionRank : null,
|
||||
regionTotal,
|
||||
farmAvgEbv,
|
||||
regionAvgEbv,
|
||||
farmAvgEpd,
|
||||
regionAvgEpd,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user