formatting
This commit is contained in:
parent
2ff7d1759e
commit
4f59f3bc14
23 changed files with 994 additions and 3338 deletions
|
|
@ -61,10 +61,12 @@ export const evaluateAnswer = async (
|
|||
store: GameSessionStore,
|
||||
): Promise<AnswerResult> => {
|
||||
const session = await store.get(submission.sessionId);
|
||||
if (!session) throw new NotFoundError(`Game session not found: ${submission.sessionId}`);
|
||||
if (!session)
|
||||
throw new NotFoundError(`Game session not found: ${submission.sessionId}`);
|
||||
|
||||
const correctOptionId = session.answers.get(submission.questionId);
|
||||
if (correctOptionId === undefined) throw new NotFoundError(`Question not found: ${submission.questionId}`);
|
||||
if (correctOptionId === undefined)
|
||||
throw new NotFoundError(`Question not found: ${submission.questionId}`);
|
||||
|
||||
// delete answered question; delete session when all questions are answered
|
||||
session.answers.delete(submission.questionId);
|
||||
|
|
@ -84,10 +86,14 @@ export const evaluateAnswer = async (
|
|||
```ts
|
||||
// ✅ option B — TTL in InMemoryGameSessionStore
|
||||
export class InMemoryGameSessionStore implements GameSessionStore {
|
||||
private sessions = new Map<string, { data: GameSessionData; expiresAt: number }>();
|
||||
private sessions = new Map<
|
||||
string,
|
||||
{ data: GameSessionData; expiresAt: number }
|
||||
>();
|
||||
private readonly ttlMs: number;
|
||||
|
||||
constructor(ttlMs = 30 * 60 * 1000) { // 30 minutes default
|
||||
constructor(ttlMs = 30 * 60 * 1000) {
|
||||
// 30 minutes default
|
||||
this.ttlMs = ttlMs;
|
||||
}
|
||||
|
||||
|
|
@ -115,15 +121,13 @@ export class InMemoryGameSessionStore implements GameSessionStore {
|
|||
|
||||
---
|
||||
|
||||
|
||||
|
||||
**Problem**
|
||||
|
||||
`GameRequest.rounds` is typed as `string` in `@lila/shared`, forcing the service to cast it every time:
|
||||
|
||||
```ts
|
||||
// ❌ why is a round count a string?
|
||||
Number(request.rounds)
|
||||
Number(request.rounds);
|
||||
```
|
||||
|
||||
**Fix — fix the schema in `@lila/shared`**
|
||||
|
|
@ -204,7 +208,10 @@ it("correct answer appears exactly once in options even if distractor matches",
|
|||
// simulate getDistractors returning the correct answer as one of the distractors
|
||||
mockGetDistractors.mockResolvedValueOnce(["cane", "wrong2", "wrong3"]);
|
||||
|
||||
const session = await createGameSession(validRequest, new InMemoryGameSessionStore());
|
||||
const session = await createGameSession(
|
||||
validRequest,
|
||||
new InMemoryGameSessionStore(),
|
||||
);
|
||||
const question = session.questions[0]!;
|
||||
const optionTexts = question.options.map((o) => o.text);
|
||||
|
||||
|
|
@ -285,16 +292,14 @@ his `sessionId`.
|
|||
|
||||
```ts
|
||||
// GameSessionStore.ts
|
||||
export type GameSessionData = {
|
||||
answers: Map<string, number>;
|
||||
userId: string;
|
||||
};
|
||||
export type GameSessionData = { answers: Map<string, number>; userId: string };
|
||||
|
||||
// evaluateAnswer
|
||||
const session = await store.get(submission.sessionId);
|
||||
|
||||
if (!session) throw new NotFoundError(`Game session not found`);
|
||||
if (session.userId !== requestingUserId) throw new NotFoundError(`Game session not found`);
|
||||
if (session.userId !== requestingUserId)
|
||||
throw new NotFoundError(`Game session not found`);
|
||||
// ^^^ same error — don't confirm the session exists to the wrong user
|
||||
```
|
||||
|
||||
|
|
@ -326,8 +331,9 @@ if (terms.length === 0) {
|
|||
it("throws when getGameTerms returns no terms", async () => {
|
||||
mockGetGameTerms.mockResolvedValue([]);
|
||||
|
||||
await expect(createGameSession(validRequest, new InMemoryGameSessionStore()))
|
||||
.rejects.toThrow("No terms found");
|
||||
await expect(
|
||||
createGameSession(validRequest, new InMemoryGameSessionStore()),
|
||||
).rejects.toThrow("No terms found");
|
||||
});
|
||||
```
|
||||
|
||||
|
|
@ -349,8 +355,9 @@ it("throws when getGameTerms returns no terms", async () => {
|
|||
it("propagates getDistractors failure", async () => {
|
||||
mockGetDistractors.mockRejectedValue(new Error("db timeout"));
|
||||
|
||||
await expect(createGameSession(validRequest, new InMemoryGameSessionStore()))
|
||||
.rejects.toThrow("db timeout");
|
||||
await expect(
|
||||
createGameSession(validRequest, new InMemoryGameSessionStore()),
|
||||
).rejects.toThrow("db timeout");
|
||||
});
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue