Skip to content

Commit 11b2d45

Browse files
committed
hotfix: edit-ranking-order
1 parent 95c1993 commit 11b2d45

File tree

3 files changed

+44
-38
lines changed

3 files changed

+44
-38
lines changed

src/domain/couple/constant/score-query.helper.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import { DataSource } from 'typeorm';
22
import { EcoVerificationStatus } from '../../member/constants/eco-verification.status.enum';
33

4+
/* 가중치 기본값 : 누적♥ 1 | 평균♥ 0.3 */
45
export interface EcoScoreWeights {
5-
cum: number; // 누적♥ 가중치 (기본 1)
6-
avg: number; // 평균♥ 가중치 (기본 0.3)
6+
cum: number;
7+
avg: number;
78
}
89

9-
/** 커플별 누적♥·인증횟수·평균♥ 집계 */
10+
/* ───────────────────────────────────────────────
11+
1) 커플별 누적♥·인증횟수·평균♥ 집계 서브쿼리
12+
─────────────────────────────────────────────── */
1013
export function coupleStatsSubQuery(ds: DataSource) {
1114
return ds
1215
.createQueryBuilder()
1316
.select([
14-
'c.id AS coupleId',
15-
'c.createdAt AS createdAt',
17+
'c.id AS coupleId',
18+
'c.createdAt AS createdAt',
1619
'c.cumulativeEcoLovePoints AS cumHeart',
1720
])
1821
.from('couple', 'c')
@@ -32,12 +35,17 @@ export function coupleStatsSubQuery(ds: DataSource) {
3235
)
3336
.addSelect('COALESCE(a.ecoCnt,0)', 'ecoCnt')
3437
.addSelect(
35-
`CASE WHEN COALESCE(a.ecoCnt,0)=0 THEN 0
36-
ELSE c.cumulativeEcoLovePoints / a.ecoCnt END`,
38+
`CASE
39+
WHEN COALESCE(a.ecoCnt,0)=0 THEN 0
40+
ELSE c.cumulativeEcoLovePoints / a.ecoCnt
41+
END`,
3742
'avgHeart',
3843
);
3944
}
4045

46+
/* ───────────────────────────────────────────────
47+
2) ecoScore(절대값) + ranking 을 추가한 공통 QB
48+
─────────────────────────────────────────────── */
4149
export function coupleScoreQB(
4250
ds: DataSource,
4351
weights: EcoScoreWeights = { cum: 1, avg: 0.3 },
@@ -55,8 +63,9 @@ export function coupleScoreQB(
5563
'b.cumHeart AS cumulativeEcoLovePoints',
5664
'b.ecoCnt AS ecoVerificationCount',
5765
])
66+
/* ecoScore = 누적♥ * 1 + 평균♥ * 0.3 (소수점 버림) */
5867
.addSelect(`FLOOR(b.cumHeart * :cumW + b.avgHeart * :avgW)`, 'ecoScore')
59-
/* 랭킹: ecoScore ↓ → 인증횟수 ↓ → 결성일 ↑ */
68+
/* ranking : ecoScore ↓ → 인증횟수 ↓ → 결성일 ↑ */
6069
.addSelect(
6170
`RANK() OVER (
6271
ORDER BY
Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,52 @@
11
import { Injectable } from '@nestjs/common';
22
import { InjectRepository } from '@nestjs/typeorm';
3-
import { DataSource, Repository } from 'typeorm';
3+
import { In, Not, Repository } from 'typeorm';
44
import { Couple } from './entities/couple.entity';
5-
import { PaginatedDto } from '../../common/dto/paginated.dto';
65
import { RankingDto } from './dto/ranking.dto';
76
import { IGNORE_COUPLE_IDS } from '../eco-verification/constant/ignore-couple-ids';
87
import { coupleScoreQB } from './constant/score-query.helper';
8+
import { PaginatedDto } from '../../common/dto/paginated.dto';
99

1010
@Injectable()
1111
export class CoupleRankingService {
1212
constructor(
1313
@InjectRepository(Couple) private coupleRepo: Repository<Couple>,
14-
private readonly dataSource: DataSource,
1514
) {}
1615

16+
/* ---------------- 랭킹 리스트 ---------------- */
1717
async getRankings(page = 1, limit = 30): Promise<PaginatedDto<RankingDto>> {
1818
const offset = (page - 1) * limit;
1919

2020
const qb = coupleScoreQB(
21-
this.dataSource,
22-
{ cum: 700, avg: 300 },
21+
this.coupleRepo.manager.connection,
22+
{ cum: 1, avg: 0.3 },
2323
IGNORE_COUPLE_IDS,
2424
)
25-
.orderBy('ecoScore', 'DESC') // 이미 윈도 함수 기준으로 맞춤
26-
.addOrderBy('b.ecoCnt', 'DESC')
27-
.addOrderBy('b.createdAt', 'ASC')
25+
.orderBy('ecoScore', 'DESC')
26+
.addOrderBy('ecoVerificationCount', 'DESC')
27+
.addOrderBy('createdAt', 'ASC')
2828
.offset(offset)
2929
.limit(limit);
3030

3131
const [rows, total] = await Promise.all([
3232
qb.getRawMany<RankingDto>(),
33-
(() => {
34-
const cntQb = this.coupleRepo.createQueryBuilder('c');
35-
if (IGNORE_COUPLE_IDS.length) {
36-
cntQb.where('c.id NOT IN (:...excludeIds)', {
37-
excludeIds: IGNORE_COUPLE_IDS,
38-
});
39-
}
40-
return cntQb.getCount();
41-
})(),
33+
this.coupleRepo.count({
34+
where: { id: Not(In(IGNORE_COUPLE_IDS)) },
35+
}),
4236
]);
4337

44-
const results: RankingDto[] = rows.map((r) => ({
45-
coupleId: r.coupleId,
46-
name: r.name,
47-
profileImageUrl: r.profileImageUrl,
48-
ecoScore: Number(r.ecoScore),
49-
cumulativeEcoLovePoints: Number(r.cumulativeEcoLovePoints),
50-
ecoVerificationCount: Number(r.ecoVerificationCount),
51-
}));
52-
53-
return { results, total, limit, page };
38+
return {
39+
results: rows.map((r) => ({
40+
coupleId: r.coupleId,
41+
name: r.name,
42+
profileImageUrl: r.profileImageUrl,
43+
ecoScore: Number(r.ecoScore),
44+
cumulativeEcoLovePoints: Number(r.cumulativeEcoLovePoints),
45+
ecoVerificationCount: Number(r.ecoVerificationCount),
46+
})),
47+
total,
48+
limit,
49+
page,
50+
};
5451
}
5552
}

src/domain/couple/couple.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ export class CoupleService {
152152
if (!couple) return null;
153153

154154
const row = await coupleScoreQB(
155-
this.dataSource,
156-
{ cum: 700, avg: 300 },
155+
this.coupleRepo.manager.connection,
156+
{ cum: 1, avg: 0.3 },
157157
IGNORE_COUPLE_IDS,
158158
)
159159
.andWhere('b.coupleId = :cid', { cid })
@@ -164,7 +164,7 @@ export class CoupleService {
164164
ecoVerificationCount: number;
165165
}>();
166166

167-
if (!row) return null;
167+
if (!row) return null; // ignore 리스트에 속할 때
168168

169169
const remainingDays = Math.max(
170170
dayjs(couple.breakupAt).diff(dayjs(tz().format('YYYY-MM-DD')), 'day'),

0 commit comments

Comments
 (0)