Skip to content

Commit 92fbc2f

Browse files
committed
Improve the leaderboard stats
1 parent cb06bc8 commit 92fbc2f

File tree

4 files changed

+150
-30
lines changed

4 files changed

+150
-30
lines changed

__tests__/src/leaderboards/stats.test.ts

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ describe("_fetchAllLeaderboardsData", () => {
3838

3939
// Tests which tests the output of the function _fetchAllLeaderboardsData
4040
// Mock the calls to getLeaderBoardData
41-
test("fetches all leaderboards data", async () => {
41+
test("fetches all leaderboards data from 2 pages", async () => {
4242
const result = await _fetchAllLeaderboardsData();
4343

44-
// I am getting 0 calls. Why?
45-
expect(getLeaderBoardData).toBeCalledTimes(16);
44+
// Now fetches 2 pages per faction/gameMode combination: 4 factions * 4 game modes * 2 pages = 32 calls
45+
expect(getLeaderBoardData).toBeCalledTimes(32);
46+
47+
// Check that page 1 calls are made (start=1)
4648
expect(getLeaderBoardData).toBeCalledWith("american", "1v1", 1, 200, 1);
4749
expect(getLeaderBoardData).toBeCalledWith("american", "2v2", 1, 200, 1);
4850
expect(getLeaderBoardData).toBeCalledWith("american", "3v3", 1, 200, 1);
@@ -52,30 +54,106 @@ describe("_fetchAllLeaderboardsData", () => {
5254
expect(getLeaderBoardData).toBeCalledWith("british", "3v3", 1, 200, 1);
5355
expect(getLeaderBoardData).toBeCalledWith("british", "4v4", 1, 200, 1);
5456

57+
// Check that page 2 calls are made (start=201)
58+
expect(getLeaderBoardData).toBeCalledWith("american", "1v1", 1, 200, 201);
59+
expect(getLeaderBoardData).toBeCalledWith("american", "2v2", 1, 200, 201);
60+
expect(getLeaderBoardData).toBeCalledWith("american", "3v3", 1, 200, 201);
61+
expect(getLeaderBoardData).toBeCalledWith("american", "4v4", 1, 200, 201);
62+
expect(getLeaderBoardData).toBeCalledWith("british", "1v1", 1, 200, 201);
63+
expect(getLeaderBoardData).toBeCalledWith("british", "2v2", 1, 200, 201);
64+
expect(getLeaderBoardData).toBeCalledWith("british", "3v3", 1, 200, 201);
65+
expect(getLeaderBoardData).toBeCalledWith("british", "4v4", 1, 200, 201);
66+
67+
// The result should have merged leaderboardStats and statGroups from both pages
68+
// Each entry should have empty arrays merged ([] + [] = [])
5569
expect(result).toEqual({
5670
american: {
57-
"1v1": exampleRawLaddersObject,
58-
"2v2": exampleRawLaddersObject,
59-
"3v3": exampleRawLaddersObject,
60-
"4v4": exampleRawLaddersObject,
71+
"1v1": {
72+
...exampleRawLaddersObject,
73+
leaderboardStats: [],
74+
statGroups: [],
75+
},
76+
"2v2": {
77+
...exampleRawLaddersObject,
78+
leaderboardStats: [],
79+
statGroups: [],
80+
},
81+
"3v3": {
82+
...exampleRawLaddersObject,
83+
leaderboardStats: [],
84+
statGroups: [],
85+
},
86+
"4v4": {
87+
...exampleRawLaddersObject,
88+
leaderboardStats: [],
89+
statGroups: [],
90+
},
6191
},
6292
british: {
63-
"1v1": exampleRawLaddersObject,
64-
"2v2": exampleRawLaddersObject,
65-
"3v3": exampleRawLaddersObject,
66-
"4v4": exampleRawLaddersObject,
93+
"1v1": {
94+
...exampleRawLaddersObject,
95+
leaderboardStats: [],
96+
statGroups: [],
97+
},
98+
"2v2": {
99+
...exampleRawLaddersObject,
100+
leaderboardStats: [],
101+
statGroups: [],
102+
},
103+
"3v3": {
104+
...exampleRawLaddersObject,
105+
leaderboardStats: [],
106+
statGroups: [],
107+
},
108+
"4v4": {
109+
...exampleRawLaddersObject,
110+
leaderboardStats: [],
111+
statGroups: [],
112+
},
67113
},
68114
dak: {
69-
"1v1": exampleRawLaddersObject,
70-
"2v2": exampleRawLaddersObject,
71-
"3v3": exampleRawLaddersObject,
72-
"4v4": exampleRawLaddersObject,
115+
"1v1": {
116+
...exampleRawLaddersObject,
117+
leaderboardStats: [],
118+
statGroups: [],
119+
},
120+
"2v2": {
121+
...exampleRawLaddersObject,
122+
leaderboardStats: [],
123+
statGroups: [],
124+
},
125+
"3v3": {
126+
...exampleRawLaddersObject,
127+
leaderboardStats: [],
128+
statGroups: [],
129+
},
130+
"4v4": {
131+
...exampleRawLaddersObject,
132+
leaderboardStats: [],
133+
statGroups: [],
134+
},
73135
},
74136
german: {
75-
"1v1": exampleRawLaddersObject,
76-
"2v2": exampleRawLaddersObject,
77-
"3v3": exampleRawLaddersObject,
78-
"4v4": exampleRawLaddersObject,
137+
"1v1": {
138+
...exampleRawLaddersObject,
139+
leaderboardStats: [],
140+
statGroups: [],
141+
},
142+
"2v2": {
143+
...exampleRawLaddersObject,
144+
leaderboardStats: [],
145+
statGroups: [],
146+
},
147+
"3v3": {
148+
...exampleRawLaddersObject,
149+
leaderboardStats: [],
150+
statGroups: [],
151+
},
152+
"4v4": {
153+
...exampleRawLaddersObject,
154+
leaderboardStats: [],
155+
statGroups: [],
156+
},
79157
},
80158
});
81159
});

components/Footer/Footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const Footer: React.FC = () => {
2222
<Container size={"lg"}>
2323
<Group justify="space-between">
2424
<Text c="dimmed" size="sm">
25-
© 2023 - 2025 COH3stats.com,{" "}
25+
© 2023 - 2026 COH3stats.com,{" "}
2626
<Tooltip
2727
multiline
2828
w={200}

components/leaderboards/leaderboard-stats.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,14 @@ const LeaderBoardStats = ({ leaderBoardStats }: { leaderBoardStats: LeaderboardS
217217
all numbers.{" "}
218218
</Text>
219219
<Space h={"xl"} />
220-
<Title order={2}>Players with ELO 1600+</Title>
221-
<StatsTable data={leaderBoardStats.topLevelPlayers} />
222-
<Space h={"xl"} />
223220
<Title order={2}>Highest ELO</Title>
224221
<StatsTable data={leaderBoardStats.topElo} />
222+
<Space h={"xl"} />
223+
<Title order={2}>Players with ELO 1600+</Title>
224+
<StatsTable data={leaderBoardStats.elo1600} />
225+
<Space h={"xl"} />
226+
<Title order={2}>Players with ELO 1800+</Title>
227+
<StatsTable data={leaderBoardStats.elo1800} />
225228
</Container>
226229
);
227230
};

src/leaderboards/stats.ts

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,33 @@ import { getLeaderBoardData } from "../coh3/coh3-api";
99
export type LeaderboardStatsType = {
1010
totalPlayers: Record<raceType, Record<leaderBoardType, number>>;
1111
topElo: Record<raceType, Record<leaderBoardType, number>>;
12-
// Counts players on level 16+
13-
topLevelPlayers: Record<raceType, Record<leaderBoardType, number>>;
12+
// Counts players with ELO 1600+
13+
elo1600: Record<raceType, Record<leaderBoardType, number>>;
14+
// Counts players with ELO 1800+
15+
elo1800: Record<raceType, Record<leaderBoardType, number>>;
1416
};
1517

1618
/**
1719
* Fetches all leaderboards data and returns it as a LeaderboardStats object.
20+
* Fetches top 2 pages (400 players total) for each faction and game mode.
1821
*/
1922
const _fetchAllLeaderboardsData = async () => {
23+
// Fetch both page 1 (start=1, count=200) and page 2 (start=201, count=200)
2024
const promises = raceTypeArray.flatMap((faction) =>
21-
leaderBoardTypeArray.map((gameMode) =>
25+
leaderBoardTypeArray.flatMap((gameMode) => [
2226
getLeaderBoardData(faction, gameMode, 1, 200, 1).then((data: any) => ({
2327
faction,
2428
gameMode,
29+
page: 1,
2530
data,
2631
})),
27-
),
32+
getLeaderBoardData(faction, gameMode, 1, 200, 201).then((data: any) => ({
33+
faction,
34+
gameMode,
35+
page: 2,
36+
data,
37+
})),
38+
]),
2839
);
2940

3041
const entries = await Promise.all(promises);
@@ -35,11 +46,30 @@ const _fetchAllLeaderboardsData = async () => {
3546
};
3647
} = {};
3748

49+
// Group entries by faction and gameMode, then merge the leaderboardStats
3850
entries.forEach(({ faction, gameMode, data }) => {
3951
if (!result[faction]) {
4052
result[faction] = {};
4153
}
42-
result[faction][gameMode] = data;
54+
55+
if (!result[faction][gameMode]) {
56+
// First page - initialize with the data
57+
result[faction][gameMode] = {
58+
...data,
59+
leaderboardStats: [...data.leaderboardStats],
60+
statGroups: [...data.statGroups],
61+
};
62+
} else {
63+
// Second page - merge the leaderboardStats and statGroups arrays
64+
result[faction][gameMode].leaderboardStats = [
65+
...result[faction][gameMode].leaderboardStats,
66+
...data.leaderboardStats,
67+
];
68+
result[faction][gameMode].statGroups = [
69+
...result[faction][gameMode].statGroups,
70+
...data.statGroups,
71+
];
72+
}
4373
});
4474

4575
return result;
@@ -62,7 +92,13 @@ const calculateLeaderboardStats = async () => {
6292
dak: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
6393
german: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
6494
};
65-
result.topLevelPlayers = {
95+
result.elo1600 = {
96+
american: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
97+
british: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
98+
dak: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
99+
german: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
100+
};
101+
result.elo1800 = {
66102
american: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
67103
british: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
68104
dak: { "1v1": 0, "2v2": 0, "3v3": 0, "4v4": 0 },
@@ -75,9 +111,12 @@ const calculateLeaderboardStats = async () => {
75111
allLeaderboardsData[race][leaderBoardType].rankTotal;
76112
result.topElo[race][leaderBoardType] =
77113
allLeaderboardsData[race][leaderBoardType].leaderboardStats[0].rating;
78-
result.topLevelPlayers[race][leaderBoardType] = allLeaderboardsData[race][
114+
result.elo1600[race][leaderBoardType] = allLeaderboardsData[race][
79115
leaderBoardType
80116
].leaderboardStats.filter((player: { rating: number }) => player.rating >= 1600).length;
117+
result.elo1800[race][leaderBoardType] = allLeaderboardsData[race][
118+
leaderBoardType
119+
].leaderboardStats.filter((player: { rating: number }) => player.rating >= 1800).length;
81120
}
82121
}
83122

0 commit comments

Comments
 (0)