Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions sql/reports/challenges/winners.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ WITH challenge_context AS (
),
submission_metrics AS (
SELECT
s.id AS submission_id,
s."memberId",
COALESCE(s."submittedDate", s."createdAt") AS submission_timestamp,
COALESCE(
final_review."aggregateScore",
s."finalScore"::double precision,
Expand Down Expand Up @@ -96,26 +98,32 @@ standard_member_scores AS (
FROM submission_metrics AS sm
GROUP BY sm."memberId"
),
mm_member_scores AS (
SELECT
mm_latest_submission_scores AS (
SELECT DISTINCT ON (sm."memberId")
sm."memberId",
MAX(sm.provisional_score) AS provisional_score_raw,
MAX(sm.final_score_raw) AS final_score_raw
sm.provisional_score AS provisional_score_raw,
sm.final_score_raw
FROM submission_metrics AS sm
GROUP BY sm."memberId"
WHERE
sm.provisional_score IS NOT NULL
OR sm.final_score_raw IS NOT NULL
ORDER BY
sm."memberId",
sm.submission_timestamp DESC NULLS LAST,
sm.submission_id DESC
),
mm_winner_scores AS (
SELECT
mms."memberId",
mlss."memberId",
CASE
WHEN mms.provisional_score_raw IS NULL THEN NULL
ELSE ROUND(mms.provisional_score_raw::numeric, 2)
WHEN mlss.provisional_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.provisional_score_raw::numeric, 2)
END AS "provisionalScore",
CASE
WHEN mms.final_score_raw IS NULL THEN NULL
ELSE ROUND(mms.final_score_raw::numeric, 2)
WHEN mlss.final_score_raw IS NULL THEN NULL
ELSE ROUND(mlss.final_score_raw::numeric, 2)
END AS "finalScore"
FROM mm_member_scores AS mms
FROM mm_latest_submission_scores AS mlss
)
SELECT
COALESCE(
Expand Down
16 changes: 16 additions & 0 deletions src/reports/challenges/challenge-export-sql.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ describe("Challenge export SQL", () => {
);
});

it.each(challengeUserSqlPaths)(
"uses the latest usable Marathon Match scored submission in %s",
(sqlPath) => {
const sql = sqlLoader.load(sqlPath);

expect(sql).toMatch(/SELECT DISTINCT ON \(\w+\."memberId"\)/);
expect(sql).toMatch(
/ORDER BY\s+\w+\."memberId",\s+\w+\.submission_timestamp DESC NULLS LAST,\s+\w+\.submission_id DESC/,
);
expect(sql).not.toMatch(
/MAX\(\w+\.provisional_score\) AS provisional_score_raw/,
);
expect(sql).not.toMatch(/MAX\(\w+\.final_score_raw\) AS final_score_raw/);
},
);

it("only returns Marathon Match winner finalRank for completed challenges", () => {
const sql = sqlLoader.load("reports/challenges/winners.sql");

Expand Down
2 changes: 1 addition & 1 deletion src/reports/report-directory.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ const REGISTERED_REPORTS_DIRECTORY: RegisteredReportsDirectory = {
challengeReport(
"Challenge Winners",
"/challenges/:challengeId/winners",
"Return the challenge winners report with placement winners only. Marathon Match exports include non-failed provisionalScore and completed challenge finalScore/finalRank values.",
"Return the challenge winners report with placement winners only. Marathon Match exports use the latest non-failed provisionalScore and include completed challenge finalScore/finalRank values.",
AppScopes.Challenge.Winners,
[challengeIdParam],
),
Expand Down
Loading