mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 07:16:17 +08:00
refactor(types): leaderboard types
move to shared types (#4774) add types to ape client (#4786)
This commit is contained in:
parent
b5465be75b
commit
15c697802d
|
@ -44,7 +44,7 @@ describe("LeaderboardsDal", () => {
|
|||
"15",
|
||||
"english",
|
||||
0
|
||||
)) as MonkeyTypes.LeaderboardEntry[];
|
||||
)) as SharedTypes.LeaderboardEntry[];
|
||||
|
||||
//THEN
|
||||
const lb = result.map((it) => _.omit(it, ["_id"]));
|
||||
|
@ -70,7 +70,7 @@ describe("LeaderboardsDal", () => {
|
|||
"60",
|
||||
"english",
|
||||
0
|
||||
)) as MonkeyTypes.LeaderboardEntry[];
|
||||
)) as SharedTypes.LeaderboardEntry[];
|
||||
|
||||
//THEN
|
||||
const lb = result.map((it) => _.omit(it, ["_id"]));
|
||||
|
|
|
@ -12,12 +12,12 @@ export async function get(
|
|||
language: string,
|
||||
skip: number,
|
||||
limit = 50
|
||||
): Promise<MonkeyTypes.LeaderboardEntry[] | false> {
|
||||
): Promise<SharedTypes.LeaderboardEntry[] | false> {
|
||||
if (leaderboardUpdating[`${language}_${mode}_${mode2}`]) return false;
|
||||
if (limit > 50 || limit <= 0) limit = 50;
|
||||
if (skip < 0) skip = 0;
|
||||
const preset = await db
|
||||
.collection<MonkeyTypes.LeaderboardEntry>(
|
||||
.collection<SharedTypes.LeaderboardEntry>(
|
||||
`leaderboards.${language}.${mode}.${mode2}`
|
||||
)
|
||||
.find()
|
||||
|
@ -31,7 +31,7 @@ export async function get(
|
|||
interface GetRankResponse {
|
||||
count: number;
|
||||
rank: number | null;
|
||||
entry: MonkeyTypes.LeaderboardEntry | null;
|
||||
entry: SharedTypes.LeaderboardEntry | null;
|
||||
}
|
||||
|
||||
export async function getRank(
|
||||
|
@ -42,7 +42,7 @@ export async function getRank(
|
|||
): Promise<GetRankResponse | false> {
|
||||
if (leaderboardUpdating[`${language}_${mode}_${mode2}`]) return false;
|
||||
const entry = await db
|
||||
.collection<MonkeyTypes.LeaderboardEntry>(
|
||||
.collection<SharedTypes.LeaderboardEntry>(
|
||||
`leaderboards.${language}.${mode}.${mode2}`
|
||||
)
|
||||
.findOne({ uid });
|
||||
|
@ -71,7 +71,7 @@ export async function update(
|
|||
const start1 = performance.now();
|
||||
const lb = db
|
||||
.collection<MonkeyTypes.User>("users")
|
||||
.aggregate<MonkeyTypes.LeaderboardEntry>(
|
||||
.aggregate<SharedTypes.LeaderboardEntry>(
|
||||
[
|
||||
{
|
||||
$match: {
|
||||
|
|
|
@ -9,14 +9,14 @@ const RECENT_AGE_MILLISECONDS = RECENT_AGE_MINUTES * 60 * 1000;
|
|||
|
||||
async function getTop10(
|
||||
leaderboardTime: string
|
||||
): Promise<MonkeyTypes.LeaderboardEntry[]> {
|
||||
): Promise<SharedTypes.LeaderboardEntry[]> {
|
||||
return (await LeaderboardsDAL.get(
|
||||
"time",
|
||||
leaderboardTime,
|
||||
"english",
|
||||
0,
|
||||
10
|
||||
)) as MonkeyTypes.LeaderboardEntry[]; //can do that because gettop10 will not be called during an update
|
||||
)) as SharedTypes.LeaderboardEntry[]; //can do that because gettop10 will not be called during an update
|
||||
}
|
||||
|
||||
async function updateLeaderboardAndNotifyChanges(
|
||||
|
|
18
backend/src/types/types.d.ts
vendored
18
backend/src/types/types.d.ts
vendored
|
@ -139,24 +139,6 @@ declare namespace MonkeyTypes {
|
|||
personalBests: SharedTypes.PersonalBests;
|
||||
}
|
||||
|
||||
interface LeaderboardEntry {
|
||||
_id: ObjectId;
|
||||
acc: number;
|
||||
consistency: number;
|
||||
difficulty: SharedTypes.Config.Difficulty;
|
||||
lazyMode: boolean;
|
||||
language: string;
|
||||
punctuation: boolean;
|
||||
raw: number;
|
||||
wpm: number;
|
||||
timestamp: number;
|
||||
uid: string;
|
||||
name: string;
|
||||
rank: number;
|
||||
badges?: Badge[];
|
||||
badgeId?: number;
|
||||
}
|
||||
|
||||
interface CustomTheme {
|
||||
_id: ObjectId;
|
||||
name: string;
|
||||
|
|
|
@ -1,24 +1,13 @@
|
|||
const BASE_PATH = "/leaderboards";
|
||||
|
||||
interface LeaderboardQuery {
|
||||
language: string;
|
||||
mode: SharedTypes.Config.Mode;
|
||||
mode2: string;
|
||||
isDaily?: boolean;
|
||||
daysBefore?: number;
|
||||
}
|
||||
|
||||
interface LeadeboardQueryWithPagination extends LeaderboardQuery {
|
||||
skip?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export default class Leaderboards {
|
||||
constructor(private httpClient: Ape.HttpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
async get(query: LeadeboardQueryWithPagination): Ape.EndpointResponse {
|
||||
async get(
|
||||
query: Ape.Leaderboards.QueryWithPagination
|
||||
): Ape.EndpointResponse<Ape.Leaderboards.GetLeaderboard> {
|
||||
const {
|
||||
language,
|
||||
mode,
|
||||
|
@ -44,7 +33,9 @@ export default class Leaderboards {
|
|||
return await this.httpClient.get(endpointPath, { searchQuery });
|
||||
}
|
||||
|
||||
async getRank(query: LeaderboardQuery): Ape.EndpointResponse {
|
||||
async getRank(
|
||||
query: Ape.Leaderboards.Query
|
||||
): Ape.EndpointResponse<Ape.Leaderboards.GetRank> {
|
||||
const { language, mode, mode2, isDaily, daysBefore } = query;
|
||||
const includeDaysBefore = (isDaily ?? false) && (daysBefore ?? 0) > 0;
|
||||
|
||||
|
|
25
frontend/src/ts/ape/types/leaderboards.d.ts
vendored
Normal file
25
frontend/src/ts/ape/types/leaderboards.d.ts
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
// for some reason when using the dot notaion, the types are not being recognized as used
|
||||
declare namespace Ape.Leaderboards {
|
||||
interface Query {
|
||||
language: string;
|
||||
mode: SharedTypes.Config.Mode;
|
||||
mode2: string;
|
||||
isDaily?: boolean;
|
||||
daysBefore?: number;
|
||||
}
|
||||
|
||||
interface QueryWithPagination extends Query {
|
||||
skip?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
type GetLeaderboard = SharedTypes.LeaderboardEntry[];
|
||||
|
||||
type GetRank = {
|
||||
minWpm: number;
|
||||
count: number;
|
||||
rank: number | null;
|
||||
entry: SharedTypes.LeaderboardEntry | null;
|
||||
};
|
||||
}
|
|
@ -21,21 +21,14 @@ let showingYesterday = false;
|
|||
type LbKey = "15" | "60";
|
||||
|
||||
let currentData: {
|
||||
[key in LbKey]: MonkeyTypes.LeaderboardEntry[];
|
||||
[key in LbKey]: SharedTypes.LeaderboardEntry[];
|
||||
} = {
|
||||
"15": [],
|
||||
"60": [],
|
||||
};
|
||||
|
||||
interface GetRankResponse {
|
||||
minWpm: number;
|
||||
count: number;
|
||||
rank: number | null;
|
||||
entry: MonkeyTypes.LeaderboardEntry | null;
|
||||
}
|
||||
|
||||
let currentRank: {
|
||||
[key in LbKey]: GetRankResponse | Record<string, never>;
|
||||
[key in LbKey]: Ape.Leaderboards.GetRank | Record<string, never>;
|
||||
} = {
|
||||
"15": {},
|
||||
"60": {},
|
||||
|
@ -438,7 +431,7 @@ async function update(): Promise<void> {
|
|||
|
||||
const timeModes = ["15", "60"];
|
||||
|
||||
const leaderboardRequests = timeModes.map(async (mode2) => {
|
||||
const lbDataRequests = timeModes.map(async (mode2) => {
|
||||
return Ape.leaderboards.get({
|
||||
language: currentLanguage,
|
||||
mode: "time",
|
||||
|
@ -447,8 +440,11 @@ async function update(): Promise<void> {
|
|||
});
|
||||
});
|
||||
|
||||
const lbRankRequests: Promise<
|
||||
Ape.HttpClientResponse<Ape.Leaderboards.GetRank>
|
||||
>[] = [];
|
||||
if (Auth?.currentUser) {
|
||||
leaderboardRequests.push(
|
||||
lbRankRequests.push(
|
||||
...timeModes.map(async (mode2) => {
|
||||
return Ape.leaderboards.getRank({
|
||||
language: currentLanguage,
|
||||
|
@ -460,26 +456,28 @@ async function update(): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
const responses = await Promise.all(leaderboardRequests);
|
||||
const responses = await Promise.all(lbDataRequests);
|
||||
const rankResponses = await Promise.all(lbRankRequests);
|
||||
|
||||
const failedResponse = responses.find((response) => response.status !== 200);
|
||||
if (failedResponse) {
|
||||
const atLeastOneFailed =
|
||||
responses.find((response) => response.status !== 200) ||
|
||||
rankResponses.find((response) => response.status !== 200);
|
||||
if (atLeastOneFailed) {
|
||||
hideLoader("15");
|
||||
hideLoader("60");
|
||||
return Notifications.add(
|
||||
"Failed to load leaderboards: " + failedResponse.message,
|
||||
"Failed to load leaderboards: " + atLeastOneFailed.message,
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
const [lb15Data, lb60Data, lb15Rank, lb60Rank] = responses.map(
|
||||
(response) => response.data
|
||||
);
|
||||
const [lb15Data, lb60Data] = responses.map((response) => response.data);
|
||||
const [lb15Rank, lb60Rank] = rankResponses.map((response) => response.data);
|
||||
|
||||
currentData["15"] = lb15Data;
|
||||
currentData["60"] = lb60Data;
|
||||
currentRank["15"] = lb15Rank;
|
||||
currentRank["60"] = lb60Rank;
|
||||
if (lb15Data !== undefined && lb15Data !== null) currentData["15"] = lb15Data;
|
||||
if (lb60Data !== undefined && lb60Data !== null) currentData["60"] = lb60Data;
|
||||
if (lb15Rank !== undefined && lb15Rank !== null) currentRank["15"] = lb15Rank;
|
||||
if (lb60Rank !== undefined && lb60Rank !== null) currentRank["60"] = lb60Rank;
|
||||
|
||||
const leaderboardKeys: LbKey[] = ["15", "60"];
|
||||
|
||||
|
@ -535,9 +533,9 @@ async function requestMore(lb: LbKey, prepend = false): Promise<void> {
|
|||
limit: limitVal,
|
||||
...getDailyLeaderboardQuery(),
|
||||
});
|
||||
const data: MonkeyTypes.LeaderboardEntry[] = response.data;
|
||||
const data = response.data;
|
||||
|
||||
if (response.status !== 200 || data.length === 0) {
|
||||
if (response.status !== 200 || data === null || data.length === 0) {
|
||||
hideLoader(lb);
|
||||
requesting[lb] = false;
|
||||
return;
|
||||
|
@ -575,7 +573,7 @@ async function requestNew(lb: LbKey, skip: number): Promise<void> {
|
|||
skip,
|
||||
...getDailyLeaderboardQuery(),
|
||||
});
|
||||
const data: MonkeyTypes.LeaderboardEntry[] = response.data;
|
||||
const data = response.data;
|
||||
|
||||
if (response.status === 503) {
|
||||
Notifications.add(
|
||||
|
@ -588,7 +586,7 @@ async function requestNew(lb: LbKey, skip: number): Promise<void> {
|
|||
clearBody(lb);
|
||||
currentData[lb] = [];
|
||||
currentAvatars[lb] = [];
|
||||
if (response.status !== 200 || data.length === 0) {
|
||||
if (response.status !== 200 || data === null || data.length === 0) {
|
||||
hideLoader(lb);
|
||||
return;
|
||||
}
|
||||
|
@ -604,11 +602,14 @@ async function requestNew(lb: LbKey, skip: number): Promise<void> {
|
|||
}
|
||||
|
||||
async function getAvatarUrls(
|
||||
data: MonkeyTypes.LeaderboardEntry[]
|
||||
data: Ape.Leaderboards.GetLeaderboard
|
||||
): Promise<(string | null)[]> {
|
||||
return Promise.allSettled(
|
||||
data.map(async (entry) =>
|
||||
Misc.getDiscordAvatarUrl(entry.discordId, entry.discordAvatar)
|
||||
Misc.getDiscordAvatarUrl(
|
||||
entry.discordId ?? undefined,
|
||||
entry.discordAvatar ?? undefined
|
||||
)
|
||||
)
|
||||
).then((promises) => {
|
||||
return promises.map((promise) => {
|
||||
|
|
21
frontend/src/ts/types/types.d.ts
vendored
21
frontend/src/ts/types/types.d.ts
vendored
|
@ -200,29 +200,10 @@ declare namespace MonkeyTypes {
|
|||
|
||||
interface Leaderboards {
|
||||
time: {
|
||||
[key in 15 | 60]: LeaderboardEntry[];
|
||||
[key in 15 | 60]: SharedTypes.LeaderboardEntry[];
|
||||
};
|
||||
}
|
||||
|
||||
interface LeaderboardEntry {
|
||||
difficulty: string;
|
||||
timestamp: number;
|
||||
language: string;
|
||||
wpm: number;
|
||||
consistency: number | "-";
|
||||
punctuation: boolean;
|
||||
acc: number;
|
||||
raw: number;
|
||||
uid?: string;
|
||||
name: string;
|
||||
discordId?: string;
|
||||
discordAvatar?: string;
|
||||
badgeId?: number;
|
||||
rank: number;
|
||||
count?: number;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
interface QuoteRatings {
|
||||
[language: string]: {
|
||||
[id: number]: number;
|
||||
|
|
16
shared-types/types.d.ts
vendored
16
shared-types/types.d.ts
vendored
|
@ -438,4 +438,20 @@ declare namespace SharedTypes {
|
|||
name: string;
|
||||
config: SharedTypes.ConfigPreset;
|
||||
}
|
||||
|
||||
interface LeaderboardEntry {
|
||||
_id: string;
|
||||
wpm: number;
|
||||
acc: number;
|
||||
timestamp: number;
|
||||
raw: number;
|
||||
consistency: number | "-";
|
||||
uid: string;
|
||||
name: string;
|
||||
discordId: string | null | undefined;
|
||||
discordAvatar: string | null | undefined;
|
||||
rank: number;
|
||||
badgeId: number | null;
|
||||
hidden?: boolean;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue