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
52 changes: 12 additions & 40 deletions open-api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1809,72 +1809,44 @@
"GlobalStat": {
"type": "object",
"properties": {
"value": {
"type": "number"
},
"rank": {
"type": "integer",
"nullable": true,
"minimum": 0,
"exclusiveMinimum": true
},
"value": {
"type": "number"
},
"percentile": {
"type": "number",
"nullable": true,
"minimum": 0,
"maximum": 1
}
},
"required": ["rank", "value", "percentile"]
"required": ["value", "rank", "percentile"]
},
"PlayerProfileGlobalStats": {
"type": "object",
"properties": {
"clears": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
},
"freshClears": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
},
"sherpas": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
},
"totalTimePlayed": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
},
"contest": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
},
"sumOfBest": {
"allOf": [
{
"$ref": "#/components/schemas/GlobalStat"
}
],
"nullable": true
"$ref": "#/components/schemas/GlobalStat"
}
},
"required": [
Expand Down
34 changes: 10 additions & 24 deletions src/routes/leaderboard/individual/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import {
getIndividualGlobalLeaderboard,
searchIndividualGlobalLeaderboard
} from "@/services/leaderboard/individual/global"
import {
getIndividualWorldFirstPowerRankingsLeaderboard,
searchIndividualWorldFirstPowerRankingsLeaderboard
} from "@/services/leaderboard/individual/power-rankings"
import { z } from "zod"

export const leaderboardIndividualGlobalRoute = new RaidHubRoute({
Expand Down Expand Up @@ -44,16 +40,11 @@ export const leaderboardIndividualGlobalRoute = new RaidHubRoute({
const { page, count, search } = req.query

if (search) {
const data = await (category === "world-first-rankings"
? searchIndividualWorldFirstPowerRankingsLeaderboard({
membershipId: search,
take: count
})
: searchIndividualGlobalLeaderboard({
membershipId: search,
take: count,
category
}))
const data = await searchIndividualGlobalLeaderboard({
membershipId: search,
take: count,
category
})

if (!data) {
return RaidHubRoute.fail(ErrorCode.PlayerNotOnLeaderboardError, {
Expand All @@ -69,16 +60,11 @@ export const leaderboardIndividualGlobalRoute = new RaidHubRoute({
entries: data.entries
})
} else {
const entries = await (category === "world-first-rankings"
? getIndividualWorldFirstPowerRankingsLeaderboard({
skip: (page - 1) * count,
take: count
})
: getIndividualGlobalLeaderboard({
skip: (page - 1) * count,
take: count,
category
}))
const entries = await getIndividualGlobalLeaderboard({
skip: (page - 1) * count,
take: count,
category
})

return RaidHubRoute.ok({
type: "individual" as const,
Expand Down
13 changes: 5 additions & 8 deletions src/routes/player/membershipId/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,14 @@

const [activityStats, globalStats, worldFirstEntries] = await statsPromises

if (!globalStats) {
throw new Error(`Unexpected error: global stats for player ${membershipId} not found`)

Check warning on line 75 in src/routes/player/membershipId/profile.ts

View workflow job for this annotation

GitHub Actions / test

75 line is not covered with tests
}

return RaidHubRoute.ok({
playerInfo: player,
stats: {
global: globalStats ?? {
clears: null,
freshClears: null,
sherpas: null,
sumOfBest: null,
totalTimePlayed: null,
contest: null
},
global: globalStats,
activity: Object.fromEntries(activityStats.map(stat => [stat.activityId, stat]))
},
worldFirstEntries: Object.fromEntries(
Expand Down
16 changes: 8 additions & 8 deletions src/schema/components/PlayerProfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ export const zPlayerProfileActivityStats = registry.register(
export const zGlobalStat = registry.register(
"GlobalStat",
z.object({
rank: zNaturalNumber(),
value: z.number(),
percentile: z.number().nonnegative().max(1)
rank: zNaturalNumber().nullable(),
percentile: z.number().nonnegative().max(1).nullable()
})
)

export type PlayerProfileGlobalStats = z.input<typeof zPlayerProfileGlobalStats>
export const zPlayerProfileGlobalStats = registry.register(
"PlayerProfileGlobalStats",
z.object({
clears: zGlobalStat.nullable(),
freshClears: zGlobalStat.nullable(),
sherpas: zGlobalStat.nullable(),
totalTimePlayed: zGlobalStat.nullable(),
contest: zGlobalStat.nullable(),
sumOfBest: zGlobalStat.nullable()
clears: zGlobalStat,
freshClears: zGlobalStat,
sherpas: zGlobalStat,
totalTimePlayed: zGlobalStat,
contest: zGlobalStat,
sumOfBest: zGlobalStat
})
)

Expand Down
6 changes: 3 additions & 3 deletions src/services/clans/clan-stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
"ranked_scores" AS (
SELECT
"membership_id",
COALESCE(wpr."score", 0) AS "score",
ROW_NUMBER() OVER (ORDER BY wpr."score" DESC) AS "intra_clan_ranking"
COALESCE(player."wfr_score", 0) AS "score",
ROW_NUMBER() OVER (ORDER BY player."wfr_score" DESC) AS "intra_clan_ranking"
FROM membership_ids
LEFT JOIN "world_first_player_rankings" wpr USING (membership_id)
LEFT JOIN player USING (membership_id)
),
"member_stats" AS (
SELECT
Expand Down Expand Up @@ -101,7 +101,7 @@
)

if (!clanStats) {
throw new TypeError("Unexpected null result from clan stats query")

Check warning on line 104 in src/services/clans/clan-stats.ts

View workflow job for this annotation

GitHub Actions / test

104 line is not covered with tests
}

return clanStats
Expand Down
19 changes: 6 additions & 13 deletions src/services/leaderboard/individual/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,20 @@
import { IndividualLeaderboardEntry } from "@/schema/components/LeaderboardData"
import { IndividualGlobalLeaderboardCategory } from "@/schema/params/IndividualGlobalLeaderboardCategory"

export const individualGlobalLeaderboardSortColumns = [
"clears",
"fresh_clears",
"sherpas",
"speed",
"total_time_played"
] as const

const categoryMap = {
clears: "clears",
"full-clears": "fresh_clears",
sherpas: "sherpas",
speedrun: "speed",
"in-raid-time": "total_time_played"
"in-raid-time": "total_time_played",
"world-first-rankings": "wfr_score"
} as const

const getColumn = (category: string) => {
const column = categoryMap[category as keyof typeof categoryMap]
if (!individualGlobalLeaderboardSortColumns.includes(column)) {
if (!column) {
// Just an extra layer of run-time validation to ensure that the column is one of the valid columns
throw new TypeError(`Invalid column: ${column}`)
throw new TypeError(`Invalid column: ${category}->${column}`)

Check warning on line 18 in src/services/leaderboard/individual/global.ts

View workflow job for this annotation

GitHub Actions / test

18 line is not covered with tests
}
return column
}
Expand All @@ -34,7 +27,7 @@
}: {
skip: number
take: number
category: Exclude<IndividualGlobalLeaderboardCategory, "world-first-rankings">
category: IndividualGlobalLeaderboardCategory
}) => {
const column = getColumn(category)

Expand Down Expand Up @@ -72,7 +65,7 @@
}: {
membershipId: bigint | string
take: number
category: Exclude<IndividualGlobalLeaderboardCategory, "world-first-rankings">
category: IndividualGlobalLeaderboardCategory
}) => {
const column = getColumn(category)

Expand Down
65 changes: 0 additions & 65 deletions src/services/leaderboard/individual/power-rankings.ts

This file was deleted.

48 changes: 0 additions & 48 deletions src/services/leaderboard/power-rankings.test.ts

This file was deleted.

11 changes: 11 additions & 0 deletions src/services/player.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ describe("getPlayerGlobalStats", () => {
expect(parsed.success).toBe(true)
}
})

it("returns the correct shape for a private profile", async () => {
const data = await getPlayerGlobalStats("4611686018467346804").catch(console.error)

const parsed = zPlayerProfileGlobalStats.safeParse(data)
if (!parsed.success) {
expect(parsed.error.errors).toEqual([])
} else {
expect(parsed.success).toBe(true)
}
})
})

describe("getWorldFirstEntries", () => {
Expand Down
Loading