From f05595ca4143420a34ad4ad01bea35a460bfd5ac Mon Sep 17 00:00:00 2001 From: Divyansh Seth Date: Tue, 28 May 2024 17:11:16 +0530 Subject: [PATCH 1/4] deck: Assigned unique id to each card. - Created an ID in the format `card-type-color-value`. - Added a `sameCardCount` array to uniquely identify cards of the same type and color. - Generated a unique ID using the format `card-type-color-value-sameCardCount[id]`. Fixes #4 --- backend/src/types.d.ts | 2 +- backend/uno-game-engine/deck.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/backend/src/types.d.ts b/backend/src/types.d.ts index a606980..0ac9c89 100644 --- a/backend/src/types.d.ts +++ b/backend/src/types.d.ts @@ -14,7 +14,7 @@ type UNOCard = { type: CardType; color: CardColor; value: CardValue; - id: undefined; + id: string; }; type Player = { diff --git a/backend/uno-game-engine/deck.ts b/backend/uno-game-engine/deck.ts index c25ebe0..a4aacce 100644 --- a/backend/uno-game-engine/deck.ts +++ b/backend/uno-game-engine/deck.ts @@ -16,6 +16,7 @@ const values = [ ]; const specialCards = ['wild', 'draw4']; const deck = []; +const sameCardCount = []; // to keep track of same cards in assigning unique id to each card /** * In a standard UNO deck, there are 108 cards. Here's the breakdown: @@ -60,8 +61,13 @@ export function makeCard( color: CardColor, value: CardValue ): UNOCard { - //todo: Implement unique identification of cards by assigning an id to each card - return { type, color, value, id: undefined }; + const id = `card-${type}-${color}-${value}`; + + if (!sameCardCount[id]) sameCardCount[id] = 0; + sameCardCount[id]++; // increment the count of same cards to assign unique id + + const uid = `${id}-${sameCardCount[id]}`; + return { type, color, value, id: uid }; } /** From ef2dc47626c6f8457c6c1629748da42c4af09d0b Mon Sep 17 00:00:00 2001 From: Divyansh Seth Date: Sat, 1 Jun 2024 00:27:48 +0530 Subject: [PATCH 2/4] deck: Implemented Fisher-Yates shuffling algorithm to shuffle the deck Fixes: #2 --- backend/tests/deck.test.ts | 23 ++++++++++++++++++++++- backend/uno-game-engine/deck.ts | 9 ++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/backend/tests/deck.test.ts b/backend/tests/deck.test.ts index 98e629a..d54e7b3 100644 --- a/backend/tests/deck.test.ts +++ b/backend/tests/deck.test.ts @@ -1,7 +1,28 @@ -import { makeCard } from '../uno-game-engine/deck'; +import { shuffle, makeCard } from '../uno-game-engine/deck'; describe('testing deck.ts', () => { test('makeCard', () => { const card = makeCard('number', 'blue', '3'); expect(card.color).toBe('blue'); }); }); +describe('shuffle function', () => { + test('should change order of elements', () => { + // Create a mock deck + const deck = [ + makeCard('number', 'red', '1'), + makeCard('number', 'blue', '2'), + makeCard('number', 'red', '1'), + makeCard('number', 'yellow', '1'), + ]; + + // Create a copy of the deck for comparison + const originalDeck = [...deck]; + shuffle(deck); + + // Check that the order of elements has changed + const orderChanged = deck.some( + (card, index) => card !== originalDeck[index] + ); + expect(orderChanged).toBe(true); + }); +}); diff --git a/backend/uno-game-engine/deck.ts b/backend/uno-game-engine/deck.ts index a4aacce..8a6c19e 100644 --- a/backend/uno-game-engine/deck.ts +++ b/backend/uno-game-engine/deck.ts @@ -74,7 +74,10 @@ export function makeCard( * This function shuffles the elements of the given array *in place* . The function behaves in a type-agnostic way. * Time complexity: O(n) */ -export function shuffle(deck: Array) { - //todo: Implement a generic shuffling algorithm - [deck[0], deck[1]] = [deck[1], deck[0]]; +export function shuffle(deck: Array) { + // Fisher-Yates shuffle algorithm to shuffle card deck + for (let i = deck.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * i); + [deck[i], deck[j]] = [deck[j], deck[i]]; + } } From a4574ab3966c3e761bd6a08fdcce623042897da4 Mon Sep 17 00:00:00 2001 From: Kislay Date: Sun, 2 Jun 2024 11:32:05 +0530 Subject: [PATCH 3/4] lint: Fix prettier and eslint conflict. The two systems conflicted over indentations in switch case. --- backend/.eslintrc.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/.eslintrc.json b/backend/.eslintrc.json index f3b3648..70fb569 100644 --- a/backend/.eslintrc.json +++ b/backend/.eslintrc.json @@ -11,7 +11,13 @@ }, "plugins": ["@typescript-eslint"], "rules": { - "indent": ["error", 4], + "indent": [ + "error", + 4, + { + "SwitchCase": 1 + } + ], "quotes": ["error", "single"], "semi": ["error", "always"] } From b5100c38b3e34a176948cd21fb3d9d686598944f Mon Sep 17 00:00:00 2001 From: Kislay Date: Sun, 2 Jun 2024 15:21:33 +0530 Subject: [PATCH 4/4] typescript: Add some compiler options. --- backend/src/types.d.ts | 4 ---- backend/tsconfig.json | 18 +++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/backend/src/types.d.ts b/backend/src/types.d.ts index 0ac9c89..4f21a45 100644 --- a/backend/src/types.d.ts +++ b/backend/src/types.d.ts @@ -27,10 +27,6 @@ type EventResult = { message: string; }; -declare global { - type GameEngine = import('./engine').GameEngine; -} - type GameEventType = 'DRAW_CARD' | 'THROW_CARD'; type GameEvent = diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 4e67a74..7444df7 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -26,7 +26,7 @@ /* Modules */ "module": "commonjs" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ + "rootDir": "./" /* Specify the root folder within your source files. */, // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ @@ -87,16 +87,16 @@ "strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */, // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + "strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */, + "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */, + "useUnknownInCatchVariables": true /* Default catch clause variables as 'unknown' instead of 'any'. */, "alwaysStrict": true /* Ensure 'use strict' is always emitted. */, - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + "noUnusedLocals": true /* Enable error reporting when local variables aren't read. */, + "noUnusedParameters": true /* Raise an error when a function parameter isn't read. */, // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + "noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ @@ -104,6 +104,6 @@ /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ + // "skipLibCheck": true /* Skip type checking all .d.ts files. */ } }