-
-
Notifications
You must be signed in to change notification settings - Fork 3k
feat: add practice typing mode (no stats, xp, or pb) (@Vishal27alpha) #7482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,7 @@ export async function getResults( | |
| limit, | ||
| offset, | ||
| }); | ||
|
|
||
| void addLog( | ||
| "user_results_requested", | ||
| { | ||
|
|
@@ -132,7 +133,10 @@ export async function getResults( | |
| uid, | ||
| ); | ||
|
|
||
| return new MonkeyResponse("Results retrieved", replaceObjectIds(results)); | ||
| return new MonkeyResponse( | ||
| "Results retrieved", | ||
| replaceObjectIds(results) as GetResultsResponse["data"], | ||
| ); | ||
| } | ||
|
|
||
| export async function getResultById( | ||
|
|
@@ -142,15 +146,23 @@ export async function getResultById( | |
| const { resultId } = req.params; | ||
|
|
||
| const result = await ResultDAL.getResult(uid, resultId); | ||
| return new MonkeyResponse("Result retrieved", replaceObjectId(result)); | ||
|
|
||
| return new MonkeyResponse( | ||
| "Result retrieved", | ||
| replaceObjectId(result) as GetResultByIdResponse["data"], | ||
| ); | ||
| } | ||
|
|
||
| export async function getLastResult( | ||
| req: MonkeyRequest, | ||
| ): Promise<GetLastResultResponse> { | ||
| const { uid } = req.ctx.decodedToken; | ||
| const result = await ResultDAL.getLastResult(uid); | ||
| return new MonkeyResponse("Result retrieved", replaceObjectId(result)); | ||
|
|
||
| return new MonkeyResponse( | ||
| "Result retrieved", | ||
| replaceObjectId(result) as GetLastResultResponse["data"], | ||
| ); | ||
| } | ||
|
|
||
| export async function deleteAll(req: MonkeyRequest): Promise<MonkeyResponse> { | ||
|
|
@@ -201,6 +213,8 @@ export async function addResult( | |
| const completedEvent = req.body.result; | ||
| completedEvent.uid = uid; | ||
|
|
||
| const isPractice = completedEvent.mode === "practice"; | ||
|
|
||
|
Comment on lines
+216
to
+217
|
||
| if (isTestTooShort(completedEvent)) { | ||
| const status = MonkeyStatusCodes.TEST_TOO_SHORT; | ||
| throw new MonkeyError(status.code, status.message); | ||
|
|
@@ -437,7 +451,7 @@ export async function addResult( | |
| let isPb = false; | ||
| let tagPbs: string[] = []; | ||
|
|
||
| if (!completedEvent.bailedOut) { | ||
| if (!completedEvent.bailedOut && !isPractice) { | ||
| [isPb, tagPbs] = await Promise.all([ | ||
| UserDAL.checkIfPb(uid, user, completedEvent), | ||
| UserDAL.checkIfTagPb(uid, user, completedEvent), | ||
|
|
@@ -629,27 +643,32 @@ export async function addResult( | |
| dbresult.keyDurationStats = keyDurationStats; | ||
| } | ||
|
|
||
| const addedResult = await ResultDAL.addResult(uid, dbresult); | ||
| let insertedId: string | undefined; | ||
|
|
||
| if (!isPractice) { | ||
| const addedResult = await ResultDAL.addResult(uid, dbresult); | ||
| insertedId = addedResult.insertedId.toHexString(); | ||
| } | ||
|
|
||
| await UserDAL.incrementXp(uid, xpGained.xp); | ||
| await UserDAL.incrementTestActivity(user, completedEvent.timestamp); | ||
|
|
||
| if (isPb) { | ||
| if (isPb && insertedId !== undefined) { | ||
| void addLog( | ||
| "user_new_pb", | ||
| `${completedEvent.mode + " " + completedEvent.mode2} ${ | ||
| `${completedEvent.mode} ${completedEvent.mode2} ${ | ||
| completedEvent.wpm | ||
| } ${completedEvent.acc}% ${completedEvent.rawWpm} ${ | ||
| completedEvent.consistency | ||
| }% (${addedResult.insertedId})`, | ||
| }% (${insertedId})`, | ||
| uid, | ||
| ); | ||
| } | ||
|
|
||
| const data: PostResultResponse = { | ||
| insertedId: insertedId ?? "practice", | ||
| isPb, | ||
|
Comment on lines
668
to
670
|
||
| tagPbs, | ||
| insertedId: addedResult.insertedId.toHexString(), | ||
| xp: xpGained.xp, | ||
| dailyXpBonus: xpGained.dailyBonus ?? false, | ||
| xpBreakdown: xpGained.breakdown ?? {}, | ||
|
|
@@ -703,7 +722,7 @@ async function calculateXp( | |
| funboxBonus: funboxBonusConfiguration, | ||
| } = xpConfiguration; | ||
|
|
||
| if (mode === "zen" || !enabled) { | ||
| if (mode === "zen" || mode === "practice" || !enabled) { | ||
| return { | ||
| xp: 0, | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -22,6 +22,7 @@ export const PersonalBestSchema = z.object({ | |||||
| export type PersonalBest = z.infer<typeof PersonalBestSchema>; | ||||||
|
|
||||||
| //used by user and config | ||||||
|
|
||||||
| export const PersonalBestsSchema = z.object({ | ||||||
| time: z.record( | ||||||
| StringNumberSchema.describe("Number of seconds as string"), | ||||||
|
|
@@ -34,7 +35,11 @@ export const PersonalBestsSchema = z.object({ | |||||
| quote: z.record(StringNumberSchema, z.array(PersonalBestSchema)), | ||||||
| custom: z.record(z.literal("custom"), z.array(PersonalBestSchema)), | ||||||
| zen: z.record(z.literal("zen"), z.array(PersonalBestSchema)), | ||||||
|
|
||||||
| // practice mode: intentionally empty, never tracked | ||||||
| practice: z.never(), | ||||||
|
||||||
| practice: z.never(), | |
| practice: z.never().optional(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isPracticecurrently only skips PB checks + DB insert, but practice is supposed to not affect stats/leaderboards. Later in this handler you still update typing stats (updateTypingStats/PublicDAL.updateStats), streak, testActivity, and potentially daily leaderboards (if config rules matchpractice). Wrap those side effects inif (!isPractice)too (or early-return with a practice-specific response) to match the mode contract.