diff --git a/sql/reports/topcoder/leaderboard-generic.sql b/sql/reports/topcoder/leaderboard-generic.sql index ae2cbcc..8983523 100644 --- a/sql/reports/topcoder/leaderboard-generic.sql +++ b/sql/reports/topcoder/leaderboard-generic.sql @@ -158,6 +158,17 @@ unique_member_submissions AS ( ms.submitted_date DESC NULLS LAST, ms.submission_id DESC ), +member_submission_counts AS ( + SELECT + cc.challenge_id, + s."memberId" AS user_id, + COUNT(*) AS submission_count + FROM challenge_context AS cc + JOIN reviews."submission" AS s + ON s."challengeId" = cc.challenge_id + AND s."memberId" IS NOT NULL + GROUP BY cc.challenge_id, s."memberId" +), challenge_prizes AS ( SELECT cps."challengeId" AS challenge_id, @@ -215,6 +226,7 @@ SELECT ums.ratingColor AS "ratingColor", ums.score AS score, ums.submitted_date AS submitted_date, + COALESCE(msc.submission_count, 1) AS "submissionCount", ROW_NUMBER() OVER ( PARTITION BY ums.challenge_id ORDER BY ums.score DESC NULLS LAST, ums.submitted_date ASC NULLS LAST, ums.user_id ASC @@ -228,6 +240,9 @@ LEFT JOIN lookups."Country" AS comp_code ON UPPER(comp_code."countryCode") = UPPER(ums.country_code) LEFT JOIN lookups."Country" AS comp_id ON UPPER(comp_id.id) = UPPER(ums.country_code) +LEFT JOIN member_submission_counts AS msc + ON msc.challenge_id = ums.challenge_id + AND msc.user_id = ums.user_id JOIN challenge_summary AS cs ON cs.challenge_id = ums.challenge_id ORDER BY ums.challenge_id, ums.score DESC NULLS LAST, ums.submitted_date ASC NULLS LAST, ums.user_id ASC; diff --git a/src/reports/topcoder/topcoder-reports.service.spec.ts b/src/reports/topcoder/topcoder-reports.service.spec.ts index 04cea85..24a4a36 100644 --- a/src/reports/topcoder/topcoder-reports.service.spec.ts +++ b/src/reports/topcoder/topcoder-reports.service.spec.ts @@ -197,6 +197,7 @@ describe("TopcoderReportsService", () => { ratingColor: "#000000", score: 123, submittedDate: "2026-08-13T00:00:00Z", + submissionCount: 1, placement: 1, challengeStatus: "ACTIVE", isAiOnlyChallenge: true, @@ -223,6 +224,7 @@ describe("TopcoderReportsService", () => { score: 123, isProvisional: true, }); + expect(resultWithRealtime.placementData[0].submissionCount).toBe(1); db.query.mockResolvedValueOnce([genericRow]); diff --git a/src/reports/topcoder/topcoder-reports.service.ts b/src/reports/topcoder/topcoder-reports.service.ts index f6e3114..fffe496 100644 --- a/src/reports/topcoder/topcoder-reports.service.ts +++ b/src/reports/topcoder/topcoder-reports.service.ts @@ -117,9 +117,11 @@ type LeaderboardGenericRow = { ratingColor: string | null; score: number; submittedDate: string; + submissionCount: string | number | null; placement: number; challengeStatus: string; isAiOnlyChallenge: boolean; + userSubmissionsCount: number; }; type LeaderboardMmRow = { @@ -1039,6 +1041,7 @@ export class TopcoderReportsService implements OnModuleDestroy { wins: Record; points: number; prizes: number; + submissionCount: number; photoURL: string | null; rating: number; ratingColor: string | null; @@ -1068,12 +1071,20 @@ export class TopcoderReportsService implements OnModuleDestroy { wins: {}, points: 0, prizes: 0, + submissionCount: 0, rating: row.rating as number, ratingColor: row.ratingColor, challengeScores: {}, }; } + const memberSubmissions = Number(row.submissionCount ?? 0); + entriesByUser[row.userId].submissionCount += Number.isFinite( + memberSubmissions, + ) + ? memberSubmissions + : 0; + const log = Math.log10(Math.max(1, row.prizePool)) + row.durationDays * (filters.pointsPerDay ?? 0); @@ -1111,6 +1122,7 @@ export class TopcoderReportsService implements OnModuleDestroy { points: entry.points, wins: entry.wins, challengeScores: entry.challengeScores, + submissionCount: entry.submissionCount, rating: entry.rating, ratingColor: entry.ratingColor, prizes: useCmsPlacementPrizes