From 70947c1c0eb1c64f88b77fb3b5d7ef0acbbb6380 Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Fri, 8 Nov 2024 18:12:42 +0300 Subject: [PATCH 01/11] Added handler in pokertable class --- src/interfaces/pokerSeat/index.ts | 2 +- src/models/pokerTable/index.ts | 72 ++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/interfaces/pokerSeat/index.ts b/src/interfaces/pokerSeat/index.ts index c9ea6c9..0ab8861 100644 --- a/src/interfaces/pokerSeat/index.ts +++ b/src/interfaces/pokerSeat/index.ts @@ -1,4 +1,4 @@ -//@collapse +//collapse import { BaseEventEmitterInterface } from "../_base"; import { PokerPlayerInterface } from "../pokerPlayer"; diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index 54352e9..5040aa7 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -11,6 +11,8 @@ import { PokerTableInterface, PokerPlayerConfig, BaseEventInterface, + PokerGameInterface, + PokerGameConfig, } from "../../interfaces"; // Import Models @@ -20,6 +22,7 @@ import { PokerSeat } from "../pokerSeat"; // Import Utils import { generateUniqueId , logger} from "../../utils"; +import { PokerGame } from "../pokerGame"; /** * @class `PokerTable` @@ -193,6 +196,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __gameInProgress: boolean = false; + private __game:PokerGameInterface|undefined = undefined; + /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS **************************************************************************************************************/ @@ -290,20 +295,18 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) seat.listenToEvent(PokerSeatEvents.OCCUPIED,{ handler:(event:BaseEventInterface) => { - + this.__startGame() }, middlewares: [ (event, next) => { - // this.__checkSeatVacancy(event, next); + this.__checkIsGameInProgress(event, next); }, (event, next) => { - // this.__occupy(event, next); + this.__checkOccupancyCount(event, next); }, ], }) } - - } } @@ -461,6 +464,15 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__seats; } + /** + * `getSeats` + * Starts a new PokerGame if there are at least two active players at the PokerTable. + * This method initiates the game flow, including assigning blinds and starting the rounds. + * @returns {number} + */ + public getGame(): PokerGameInterface|undefined { + return this.__game; + } /** * `getSeats` @@ -678,6 +690,21 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__gameInProgress; } + /** + * `setSeats` + * @public + * Returns the poker table's `id`. + * @returns {number} The poker table's `id`. + * + * @example + * const rank = card.getRank(); + * console.log(rank); // "A" + */ + private __setGame(game: PokerGameInterface|undefined): PokerGameInterface|undefined { + this.__game = game; + return this.__game; + } + private __occupySeat( position: number, player: PokerPlayerInterface @@ -717,10 +744,43 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { ); return false; } + + event.lastModifiedAt = new Date(); + next(); + } + private __checkOccupancyCount( + event: BaseEventInterface, + next: () => void + ): void | false { + let occupiedSeats = 0; + + for (let i = 0; i < this.getSeats().length; i++) { + let seat = this.getSeats()[i]; + if (seat.getPlayer()) { + occupiedSeats += 1; + } + } + + // Check if all seats are occupied + if (occupiedSeats === this.getSeats().length) { + logger.log( + LogLevel.WARN, + "All seats are occupied", + event + ) + return false; + } + + // Update the event timestamp and call the next middleware function event.lastModifiedAt = new Date(); next(); } -} + private __startGame() { + let config:PokerGameConfig= {smallBlind:this.getSmallBlind(),bigBlind:this.getBigBlind(),players:[]} + let newGame = new PokerGame(config) + this.__setGame(newGame); + } +} export { PokerTable }; From 9efb47618ec5633d35dde3dabfb7b2a9f353c0e9 Mon Sep 17 00:00:00 2001 From: Astitv Singh Date: Fri, 8 Nov 2024 20:44:38 +0530 Subject: [PATCH 02/11] `Formatted PokerTable model` `Summary` A brief one-line summary of the changes made in this commit. `Description` A detailed description of the changes introduced by this commit. Include information about why the changes were made, how they address specific issues or requirements, and any relevant context or considerations. `Type` Specify the type of change represented by this commit. Choose only one of the following options: - Feature: A new feature or enhancement added to the project. - Fix: A bug fix or resolution to an issue. - Refactor: Code refactoring or restructuring without changing behavior. - Documentation: Updates or additions to documentation files. - Test: Additions or modifications to tests. - Chore: Routine maintenance tasks, such as dependency updates or code cleanup. `Impact` Describe the impact of this change on the project. Consider factors such as functionality, performance, compatibility, and user experience. `Related Issues` List any related issues or tickets addressed by this commit. Use GitHub issue numbers or links to reference specific issues. `Dependencies` Specify any dependencies or requirements associated with this commit. Include information about libraries, frameworks, or other components affected by the changes. `Testing` Describe the testing approach or strategy used to validate this change. Include details about test cases, scenarios, or environments used for testing. `Notes` Add any additional notes, comments, or considerations relevant to this commit. This may include warnings, caveats, or follow-up tasks for future work. `Commit Checklist`: - [ ] The commit message follows the established format and guidelines. - [ ] The changes introduced by the commit have been thoroughly reviewed and tested. - [ ] Any related issues or tickets have been appropriately linked or referenced. - [ ] Documentation has been updated to reflect the changes introduced by the commit. - [ ] The commit does not introduce any new linting errors, warnings, or regressions. `Branch` On branch `Changes` Changes to be committed: --- src/models/pokerTable/index.ts | 64 +++++++++++++++++----------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index 5040aa7..6215361 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -1,7 +1,7 @@ //@collapse // Import Enums -import { PokerSeatEvents , LogLevel } from "../../enums"; +import { PokerSeatEvents, LogLevel } from "../../enums"; // Import Interfaces import { @@ -21,7 +21,7 @@ import { PokerPlayer } from "../pokerPlayer"; import { PokerSeat } from "../pokerSeat"; // Import Utils -import { generateUniqueId , logger} from "../../utils"; +import { generateUniqueId, logger } from "../../utils"; import { PokerGame } from "../pokerGame"; /** @@ -196,7 +196,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __gameInProgress: boolean = false; - private __game:PokerGameInterface|undefined = undefined; + private __game: PokerGameInterface | undefined = undefined; /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS @@ -293,9 +293,9 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__seats?.push(seat); // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) - seat.listenToEvent(PokerSeatEvents.OCCUPIED,{ - handler:(event:BaseEventInterface) => { - this.__startGame() + seat.listenToEvent(PokerSeatEvents.OCCUPIED, { + handler: (event: BaseEventInterface) => { + this.__startGame(); }, middlewares: [ (event, next) => { @@ -305,9 +305,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__checkOccupancyCount(event, next); }, ], - }) + }); } - } } @@ -464,16 +463,16 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__seats; } - /** + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - public getGame(): PokerGameInterface|undefined { + public getGame(): PokerGameInterface | undefined { return this.__game; } - + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. @@ -678,19 +677,18 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return true; } - /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - private __setGameInProgress(bool:boolean): boolean { - this.__gameInProgress = bool ; + private __setGameInProgress(bool: boolean): boolean { + this.__gameInProgress = bool; return this.__gameInProgress; } - /** + /** * `setSeats` * @public * Returns the poker table's `id`. @@ -700,9 +698,11 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * const rank = card.getRank(); * console.log(rank); // "A" */ - private __setGame(game: PokerGameInterface|undefined): PokerGameInterface|undefined { - this.__game = game; - return this.__game; + private __setGame( + game: PokerGameInterface | undefined + ): PokerGameInterface | undefined { + this.__game = game; + return this.__game; } private __occupySeat( @@ -723,17 +723,17 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } - /** + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. * * @param {BaseEventInterface} event - The event object containing event data. * @param {() => void} next - The next middleware function to call if seat is available. */ - private __checkIsGameInProgress( + private __checkIsGameInProgress( event: BaseEventInterface, next: () => void - ): void|false { + ): void | false { if (this.isGameInProgress()) { logger.log( LogLevel.WARN, @@ -744,7 +744,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { ); return false; } - + event.lastModifiedAt = new Date(); next(); } @@ -754,32 +754,32 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { next: () => void ): void | false { let occupiedSeats = 0; - + for (let i = 0; i < this.getSeats().length; i++) { let seat = this.getSeats()[i]; if (seat.getPlayer()) { occupiedSeats += 1; } } - + // Check if all seats are occupied if (occupiedSeats === this.getSeats().length) { - logger.log( - LogLevel.WARN, - "All seats are occupied", - event - ) + logger.log(LogLevel.WARN, "All seats are occupied", event); return false; } - + // Update the event timestamp and call the next middleware function event.lastModifiedAt = new Date(); next(); } private __startGame() { - let config:PokerGameConfig= {smallBlind:this.getSmallBlind(),bigBlind:this.getBigBlind(),players:[]} - let newGame = new PokerGame(config) + let config: PokerGameConfig = { + smallBlind: this.getSmallBlind(), + bigBlind: this.getBigBlind(), + players: [], + }; + let newGame = new PokerGame(config); this.__setGame(newGame); } } From 7534401cdeb987c77077dd41c343240f0c94bc9c Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Sat, 9 Nov 2024 15:37:23 +0300 Subject: [PATCH 03/11] Added players list middleware in pokertable class --- src/models/pokerTable/index.ts | 123 ++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index 6215361..f9aa796 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -1,7 +1,7 @@ //@collapse // Import Enums -import { PokerSeatEvents, LogLevel } from "../../enums"; +import { PokerSeatEvents , LogLevel } from "../../enums"; // Import Interfaces import { @@ -21,7 +21,7 @@ import { PokerPlayer } from "../pokerPlayer"; import { PokerSeat } from "../pokerSeat"; // Import Utils -import { generateUniqueId, logger } from "../../utils"; +import { generateUniqueId , logger} from "../../utils"; import { PokerGame } from "../pokerGame"; /** @@ -175,6 +175,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __seats: PokerSeatInterface[] = []; + /** * @property {boolean} __gameInProgress * @@ -196,7 +197,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __gameInProgress: boolean = false; - private __game: PokerGameInterface | undefined = undefined; + private __game:PokerGameInterface|undefined = undefined; + /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS @@ -293,9 +295,9 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__seats?.push(seat); // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) - seat.listenToEvent(PokerSeatEvents.OCCUPIED, { - handler: (event: BaseEventInterface) => { - this.__startGame(); + seat.listenToEvent(PokerSeatEvents.OCCUPIED,{ + handler:(event:BaseEventInterface) => { + this.__startGame(event) }, middlewares: [ (event, next) => { @@ -304,9 +306,13 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { (event, next) => { this.__checkOccupancyCount(event, next); }, + (event, next) => { + this.__createGamePlayersList(event, next); + }, ], - }); + }) } + } } @@ -463,16 +469,17 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__seats; } - /** + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - public getGame(): PokerGameInterface | undefined { + public getGame(): PokerGameInterface|undefined { return this.__game; } + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. @@ -677,18 +684,20 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return true; } + + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - private __setGameInProgress(bool: boolean): boolean { - this.__gameInProgress = bool; + private __setGameInProgress(bool:boolean): boolean { + this.__gameInProgress = bool ; return this.__gameInProgress; } - /** + /** * `setSeats` * @public * Returns the poker table's `id`. @@ -698,11 +707,9 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * const rank = card.getRank(); * console.log(rank); // "A" */ - private __setGame( - game: PokerGameInterface | undefined - ): PokerGameInterface | undefined { - this.__game = game; - return this.__game; + private __setGame(game: PokerGameInterface|undefined): PokerGameInterface|undefined { + this.__game = game; + return this.__game; } private __occupySeat( @@ -723,17 +730,17 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } - /** + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. * * @param {BaseEventInterface} event - The event object containing event data. * @param {() => void} next - The next middleware function to call if seat is available. */ - private __checkIsGameInProgress( + private __checkIsGameInProgress( event: BaseEventInterface, next: () => void - ): void | false { + ): void|false { if (this.isGameInProgress()) { logger.log( LogLevel.WARN, @@ -744,7 +751,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { ); return false; } - + event.lastModifiedAt = new Date(); next(); } @@ -754,32 +761,84 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { next: () => void ): void | false { let occupiedSeats = 0; - + for (let i = 0; i < this.getSeats().length; i++) { let seat = this.getSeats()[i]; if (seat.getPlayer()) { occupiedSeats += 1; } } - + // Check if all seats are occupied if (occupiedSeats === this.getSeats().length) { - logger.log(LogLevel.WARN, "All seats are occupied", event); + logger.log( + LogLevel.WARN, + "All seats are occupied", + event + ) return false; } - + // Update the event timestamp and call the next middleware function event.lastModifiedAt = new Date(); + event.occupancyCount = occupiedSeats; + next(); + } + + + private __createGamePlayersList( + event: BaseEventInterface, + next: () => void + ): void | false { + + if (event.occupancyCount >= 2) { + let players:PokerPlayerInterface[] = []; + let isDealerPosition = 0; + + this.getSeats().forEach((seat,index) => { + let player = seat.getPlayer(); + + if (player) { + if (seat.isDealer()) { + players.push(player); + isDealerPosition = index; + } + } + }); + + for (let i = 0; i < 2; i++) { + if (i=0) { + for (let j = 0; j < this.getSeats().length; j++) { + let seat = this.getSeats()[j]; + let player = seat.getPlayer(); + if (player && seat.getPosition() > isDealerPosition) { + players.push(player); + } + } + } + + else if(i=1){ + for (let k = 0; k < this.getSeats().length; k++) { + let seat = this.getSeats()[k]; + let player = seat.getPlayer(); + if (player && seat.getPosition() < isDealerPosition) { + players.push(player); + } + } + } + + } + + event.players = players; + event.dealerPosition = isDealerPosition; + event.lastModifiedAt = new Date(); + } next(); } - private __startGame() { - let config: PokerGameConfig = { - smallBlind: this.getSmallBlind(), - bigBlind: this.getBigBlind(), - players: [], - }; - let newGame = new PokerGame(config); + private __startGame(event:BaseEventInterface) : void { + let config:PokerGameConfig= {smallBlind:this.getSmallBlind(),bigBlind:this.getBigBlind(),players:event.players} + let newGame = new PokerGame(config) this.__setGame(newGame); } } From 063e2f359265801af59511df2cbc5d70efc22bec Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Sat, 9 Nov 2024 15:59:37 +0300 Subject: [PATCH 04/11] updated --- src/models/pokerTable/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index f9aa796..dfc81dc 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -1,7 +1,7 @@ //@collapse // Import Enums -import { PokerSeatEvents , LogLevel } from "../../enums"; +import { PokerSeatEvents , LogLevel, Source } from "../../enums"; // Import Interfaces import { @@ -294,6 +294,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); this.__seats?.push(seat); + seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) seat.listenToEvent(PokerSeatEvents.OCCUPIED,{ handler:(event:BaseEventInterface) => { @@ -841,5 +842,9 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { let newGame = new PokerGame(config) this.__setGame(newGame); } + + private __seatOccupancyUpdateEventHandler(event:BaseEventInterface) : void|false { + this.emitEvent("startGame",{event:{source:Source.POKER_TABLE,data:{}}}) + } } export { PokerTable }; From eaf8eae31b848dee8593804326042e179c56168b Mon Sep 17 00:00:00 2001 From: Astitv Singh Date: Sat, 9 Nov 2024 18:51:46 +0530 Subject: [PATCH 05/11] Updated --- src/models/pokerTable/index.ts | 105 ++++++++++++++++----------------- 1 file changed, 50 insertions(+), 55 deletions(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index dfc81dc..de45b6e 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -1,7 +1,7 @@ //@collapse // Import Enums -import { PokerSeatEvents , LogLevel, Source } from "../../enums"; +import { PokerSeatEvents, LogLevel, Source } from "../../enums"; // Import Interfaces import { @@ -21,7 +21,7 @@ import { PokerPlayer } from "../pokerPlayer"; import { PokerSeat } from "../pokerSeat"; // Import Utils -import { generateUniqueId , logger} from "../../utils"; +import { generateUniqueId, logger } from "../../utils"; import { PokerGame } from "../pokerGame"; /** @@ -175,7 +175,6 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __seats: PokerSeatInterface[] = []; - /** * @property {boolean} __gameInProgress * @@ -197,8 +196,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __gameInProgress: boolean = false; - private __game:PokerGameInterface|undefined = undefined; - + private __game: PokerGameInterface | undefined = undefined; /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS @@ -294,11 +292,11 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); this.__seats?.push(seat); - seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) + seat.on(PokerSeatEvents.OCCUPIED, (event) => {}); // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) - seat.listenToEvent(PokerSeatEvents.OCCUPIED,{ - handler:(event:BaseEventInterface) => { - this.__startGame(event) + seat.listenToEvent(PokerSeatEvents.OCCUPIED, { + handler: (event: BaseEventInterface) => { + this.__startGame(event); }, middlewares: [ (event, next) => { @@ -311,9 +309,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__createGamePlayersList(event, next); }, ], - }) + }); } - } } @@ -470,17 +467,16 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__seats; } - /** + /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - public getGame(): PokerGameInterface|undefined { + public getGame(): PokerGameInterface | undefined { return this.__game; } - /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. @@ -685,20 +681,18 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return true; } - - /** * `getSeats` * Starts a new PokerGame if there are at least two active players at the PokerTable. * This method initiates the game flow, including assigning blinds and starting the rounds. * @returns {number} */ - private __setGameInProgress(bool:boolean): boolean { - this.__gameInProgress = bool ; + private __setGameInProgress(bool: boolean): boolean { + this.__gameInProgress = bool; return this.__gameInProgress; } - /** + /** * `setSeats` * @public * Returns the poker table's `id`. @@ -708,9 +702,11 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * const rank = card.getRank(); * console.log(rank); // "A" */ - private __setGame(game: PokerGameInterface|undefined): PokerGameInterface|undefined { - this.__game = game; - return this.__game; + private __setGame( + game: PokerGameInterface | undefined + ): PokerGameInterface | undefined { + this.__game = game; + return this.__game; } private __occupySeat( @@ -731,17 +727,17 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } - /** + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. * * @param {BaseEventInterface} event - The event object containing event data. * @param {() => void} next - The next middleware function to call if seat is available. */ - private __checkIsGameInProgress( + private __checkIsGameInProgress( event: BaseEventInterface, next: () => void - ): void|false { + ): void | false { if (this.isGameInProgress()) { logger.log( LogLevel.WARN, @@ -752,7 +748,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { ); return false; } - + event.lastModifiedAt = new Date(); next(); } @@ -762,41 +758,35 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { next: () => void ): void | false { let occupiedSeats = 0; - + for (let i = 0; i < this.getSeats().length; i++) { let seat = this.getSeats()[i]; if (seat.getPlayer()) { occupiedSeats += 1; } } - + // Check if all seats are occupied if (occupiedSeats === this.getSeats().length) { - logger.log( - LogLevel.WARN, - "All seats are occupied", - event - ) + logger.log(LogLevel.WARN, "All seats are occupied", event); return false; } - + // Update the event timestamp and call the next middleware function event.lastModifiedAt = new Date(); event.occupancyCount = occupiedSeats; next(); } - private __createGamePlayersList( event: BaseEventInterface, next: () => void ): void | false { - if (event.occupancyCount >= 2) { - let players:PokerPlayerInterface[] = []; + let players: PokerPlayerInterface[] = []; let isDealerPosition = 0; - this.getSeats().forEach((seat,index) => { + this.getSeats().forEach((seat, index) => { let player = seat.getPlayer(); if (player) { @@ -808,28 +798,25 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); for (let i = 0; i < 2; i++) { - if (i=0) { + if ((i = 0)) { for (let j = 0; j < this.getSeats().length; j++) { let seat = this.getSeats()[j]; let player = seat.getPlayer(); if (player && seat.getPosition() > isDealerPosition) { - players.push(player); - } - } - } - - else if(i=1){ + players.push(player); + } + } + } else if ((i = 1)) { for (let k = 0; k < this.getSeats().length; k++) { let seat = this.getSeats()[k]; let player = seat.getPlayer(); if (player && seat.getPosition() < isDealerPosition) { - players.push(player); - } - } + players.push(player); + } + } } - } - + event.players = players; event.dealerPosition = isDealerPosition; event.lastModifiedAt = new Date(); @@ -837,14 +824,22 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { next(); } - private __startGame(event:BaseEventInterface) : void { - let config:PokerGameConfig= {smallBlind:this.getSmallBlind(),bigBlind:this.getBigBlind(),players:event.players} - let newGame = new PokerGame(config) + private __startGame(event: BaseEventInterface): void { + let config: PokerGameConfig = { + smallBlind: this.getSmallBlind(), + bigBlind: this.getBigBlind(), + players: event.players, + }; + let newGame = new PokerGame(config); this.__setGame(newGame); } - private __seatOccupancyUpdateEventHandler(event:BaseEventInterface) : void|false { - this.emitEvent("startGame",{event:{source:Source.POKER_TABLE,data:{}}}) + private __seatOccupancyUpdateEventHandler( + event: BaseEventInterface + ): void | false { + this.emitEvent("startGame", { + event: { source: Source.POKER_TABLE, data: {} }, + }); } } export { PokerTable }; From 9d18751825c5a55cf8acf623bf8d71f9c0531dcd Mon Sep 17 00:00:00 2001 From: Astitv Singh Date: Sat, 9 Nov 2024 19:56:26 +0530 Subject: [PATCH 06/11] Updated --- src/enums/events/index.ts | 8 ++ src/enums/events/pokerTable/index.ts | 12 ++ src/models/pokerTable/index.ts | 167 ++++++++++++--------------- 3 files changed, 93 insertions(+), 94 deletions(-) diff --git a/src/enums/events/index.ts b/src/enums/events/index.ts index 2ec9dad..fc1ebf1 100644 --- a/src/enums/events/index.ts +++ b/src/enums/events/index.ts @@ -17,6 +17,14 @@ export * as CasinoEventsEnumModule from "./casino"; export * from "./casino"; export * as DeckEventsEnumModule from "./deck"; export * from "./deck"; +export * as PokerGameEventsEnumModule from "./pokerGame"; +export * from "./pokerGame"; +export * as PokerPhaseEventsEnumModule from "./pokerPhase"; +export * from "./pokerPhase"; +export * as PokerPlayerEventsEnumModule from "./pokerPlayer"; +export * from "./pokerPlayer"; +export * as PokerRoomEventsEnumModule from "./pokerRoom"; +export * from "./pokerRoom"; export * as PokerSeatEventsEnumModule from "./pokerSeat"; export * from "./pokerSeat"; export * as PokerTableEventsEnumModule from "./pokerTable"; diff --git a/src/enums/events/pokerTable/index.ts b/src/enums/events/pokerTable/index.ts index 77b2037..7aee39b 100644 --- a/src/enums/events/pokerTable/index.ts +++ b/src/enums/events/pokerTable/index.ts @@ -40,6 +40,18 @@ enum PokerTableEvents { * ``` */ INITIALIZED = "PokerTable:Initialized", + + /** + * Indicates that the seat has been initialized and is ready for occupancy. + * + * @example + * ```typescript + * const seatEvent: PokerTableEvents = PokerTableEvents.INITIALIZED; + * console.log(seatEvent); + * // Console Output: "PokerTable:Initialized" + * ``` + */ + NEW_GAME = "PokerTable:NewGame", } export { PokerTableEvents }; diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index de45b6e..7ce6cbf 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -1,7 +1,12 @@ //@collapse // Import Enums -import { PokerSeatEvents, LogLevel, Source } from "../../enums"; +import { + PokerSeatEvents, + LogLevel, + Source, + PokerTableEvents, +} from "../../enums"; // Import Interfaces import { @@ -133,7 +138,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * console.log(table.getSmallBlind()); // Console Output: 5 * ``` */ - private __smallBlind: number = 5; + private __smallBlind: number = 1; /** * @property {number} __bigBlindAmount @@ -280,8 +285,16 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { */ private __init(config?: PokerTableConfig): void { if (config) { - this.__id = config.id ? config.id : generateUniqueId(); - this.__smallBlind = config.smallBlind ? config.smallBlind : 5; + // Set the unique seat ID; generate a new ID if not provided. + config.id && config.id !== `` + ? this.__setId(config.id) + : this.__setId(generateUniqueId()); + + // Set the unique seat ID; generate a new ID if not provided. + config.smallBlind && config.smallBlind > 0 + ? this.__setSmallBlind(config.smallBlind) + : this.__setSmallBlind(this.__smallBlind || 1); + this.__bigBlindAmount = this.__smallBlind * 2; this.__seats = []; this.__gameInProgress = false; @@ -292,24 +305,27 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); this.__seats?.push(seat); - seat.on(PokerSeatEvents.OCCUPIED, (event) => {}); - // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) - seat.listenToEvent(PokerSeatEvents.OCCUPIED, { - handler: (event: BaseEventInterface) => { - this.__startGame(event); - }, - middlewares: [ - (event, next) => { - this.__checkIsGameInProgress(event, next); - }, - (event, next) => { - this.__checkOccupancyCount(event, next); - }, - (event, next) => { - this.__createGamePlayersList(event, next); - }, - ], + seat.on(PokerSeatEvents.OCCUPIED, (event) => { + this.__seatOccupancyUpdateEventHandler(); }); + + // // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) + // seat.listenToEvent(PokerSeatEvents.OCCUPIED, { + // handler: (event: BaseEventInterface) => { + // this.__startGame(event); + // }, + // middlewares: [ + // (event, next) => { + // this.__checkIfGameInProgress(event, next); + // }, + // (event, next) => { + // this.__checkOccupancyCount(event, next); + // }, + // (event, next) => { + // this.__createGamePlayersList(event, next); + // }, + // ], + // }); } } } @@ -361,54 +377,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * ``` */ public setName(name: string): string { - return this._setName(name); - } - - /** - * #### Description - * Sets the queue of players waiting to enter the `PokerTable` within the `PokerRoom`. This queue helps - * manage player flow and assign seating as tables become available. - * - * #### Implements - * `N/A` - This method is part of the `PokerRoomInterface` and does not implement any external methods. - * - * #### Overrides - * `N/A` - This method does not override any superclass or parent methods. - * - * #### Purpose - * The `setQueue` method provides a structured way to set or update the player queue. This queue is essential - * for room management, helping to keep a record of players awaiting entry and manage seating arrangements. - * - * #### Events - * `N/A` - No events are emitted by this method. - * - * #### Parameters - * - `queue`: An array of `PokerPlayerInterface` objects, each representing a player awaiting entry into the room’s `PokerTable`. - * - * #### Requirements - * - `queue` should be an array of valid `PokerPlayerInterface` instances. - * - If empty, the queue indicates that no players are currently waiting for entry. - * - * #### Returns - * - Returns the `queue` array after updating it within the room. - * - * #### Usage - * Use this method to set or update the player queue in cases where player flow needs control, - * ensuring smooth transitions as players are seated at the table. - * - * @param {number} smallBlind - The new list of players waiting to enter the table. - * @returns {number} - Returns the updated player queue. - * - * @example - * ```typescript - * const pokerRoom = new PokerRoom({ name: "Room2", tableSize: 6 }); - * const queue = [new PokerPlayer("Alice"), new PokerPlayer("Bob")]; - * pokerRoom.setQueue(queue); // Sets the player queue - * console.log(pokerRoom.getQueue()); // Logs the updated player queue - * ``` - */ - public setSmallBlind(smallBlind: number): number { - return this._setSmallBlind(smallBlind); + return this.__setName(name); } /************************************************************************************************************** @@ -494,8 +463,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * update */ public updateBlinds(smallBlind: number) { - this._setSmallBlind(smallBlind); - this._setBigBlind(this.getSmallBlind() * 2); + this.__setSmallBlind(smallBlind); + this.__setBigBlind(this.getSmallBlind() * 2); return true; } @@ -630,23 +599,6 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * INTERNAL METHODS (PROTECTED) **************************************************************************************************************/ - protected _setName(name: string): string { - this.__name = name; - return this.__name; - } - - protected _setSmallBlind(smallBlind: number): number { - if (smallBlind <= 0) { - throw new Error(`Small Blind should always be greator than 0.`); - } else { - return (this.__smallBlind = smallBlind); - } - } - - protected _setBigBlind(bigBlind: number): number { - return (this.__bigBlindAmount = bigBlind); - } - /************************************************************************************************************** * INTERNAL METHODS (PRIVATE) **************************************************************************************************************/ @@ -666,6 +618,27 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return this.__id; } + private __setName(name: string): string { + this.__name = name; + return this.__name; + } + + private __setSmallBlind(smallBlind: number): number { + if (smallBlind <= 0) { + throw new Error( + `${Source.POKER_TABLE}: Small Blind should always be greator than 0.` + ); + } + + // Set the small blind for the table and return it. + this.__smallBlind = smallBlind; + return this.__smallBlind; + } + + private __setBigBlind(bigBlind: number): number { + return (this.__bigBlindAmount = bigBlind); + } + /** * `setSeats` * @public @@ -734,7 +707,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * @param {BaseEventInterface} event - The event object containing event data. * @param {() => void} next - The next middleware function to call if seat is available. */ - private __checkIsGameInProgress( + private __checkIfGameInProgress( event: BaseEventInterface, next: () => void ): void | false { @@ -834,11 +807,17 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__setGame(newGame); } - private __seatOccupancyUpdateEventHandler( - event: BaseEventInterface - ): void | false { - this.emitEvent("startGame", { - event: { source: Source.POKER_TABLE, data: {} }, + private __seatOccupancyUpdateEventHandler(event?: BaseEventInterface): void { + this.emitEvent(PokerTableEvents.NEW_GAME, { + event: { source: Source.POKER_TABLE, data: { tableId: this.getId() } }, + middlewares: [ + (event, next) => { + this.__checkIfGameInProgress(event, next); + }, + (event, next) => { + this.__checkOccupancyCount(event, next); + }, + ], }); } } From e27ec6354abe8467788019829d160e09154374c3 Mon Sep 17 00:00:00 2001 From: Astitv Singh Date: Sat, 9 Nov 2024 20:29:41 +0530 Subject: [PATCH 07/11] Updated --- src/models/_base/index.ts | 153 ++++---------------------------------- 1 file changed, 14 insertions(+), 139 deletions(-) diff --git a/src/models/_base/index.ts b/src/models/_base/index.ts index 129b32d..e20ef7b 100644 --- a/src/models/_base/index.ts +++ b/src/models/_base/index.ts @@ -6,7 +6,10 @@ import { EventEmitter } from "events"; import { LogLevel } from "../../enums"; // Import Interfaces -import { BaseEventEmitterInterface, BaseEventInterface } from "../../interfaces"; +import { + BaseEventEmitterInterface, + BaseEventInterface, +} from "../../interfaces"; // Import Utils import { generateUniqueId, logger } from "../../utils"; @@ -147,71 +150,14 @@ class BaseEventEmitter data: { [key: string]: any }; [key: string]: any; }; - middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false>; + middlewares?: Array< + (event: BaseEventInterface, next: () => void) => void | false + >; } ): void { this.__emitEvent(eventName, options); } - /** - * #### Description - * The `emitEvent` method is a public method for emitting events, with an optional configuration that allows - * middleware processing. Middleware functions can intercept and transform the event before it reaches the listeners, - * allowing custom validation or data modifications. - * - * #### Purpose - * This method enables flexible event emission with support for middleware, providing a robust event processing - * mechanism in the `BaseEventEmitter`. It’s useful for customizing event behavior based on application-specific needs. - * - * #### Implements - * N/A - * - * #### Overrides - * N/A - * - * #### Events - * This method can emit any event specified by `eventName`, which can then be processed by middleware functions if defined. - * - * #### Parameters - * - `eventName: string` - The name of the event to emit. - * - `options: { event: { data: { [key: string]: any }; [key: string]: any; }, middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false> }` - * - **event** - The primary event data to emit, containing specific details. - * - **middlewares** - An optional array of middleware functions that process the event before emission. - * - * #### Requirements - * - `eventName` must be a valid string. - * - `options.event` should include relevant data for the event. If `middlewares` are provided, they should be functions with an event and next parameter. - * - * #### Returns - * - `void` - This method does not return a value. - * - * #### Usage - * Use this method to emit events with middleware-based customization, which allows for specific processing - * logic or transformations before the event reaches listeners. - * - * @param {string} eventName - The name of the event to emit. - * @param {object} options - Configuration for the event and optional middleware functions. - * - * @example - * ```typescript - * emitter.emitEvent("game:started", { - * event: { data: { gameId: "001", status: "active" } }, - * middlewares: [ - * (event, next) => { console.log("Processing event:", event); next(); }, - * (event, next) => { event.data.processed = true; next(); } - * ] - * }); - * ``` - */ - public listenToEvent( - eventName: string, - options: { - handler: (event: BaseEventInterface) => void; - middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false>; - } - ): void { - this.__listenToEvent(eventName, options); - } /************************************************************************************************************** * WRAPPER METHODS (UTILITY & CONVENIENCE) **************************************************************************************************************/ @@ -274,10 +220,15 @@ class BaseEventEmitter data: { [key: string]: any }; [key: string]: any; }; - middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false>; + middlewares?: Array< + (event: BaseEventInterface, next: () => void) => void | false + >; } ): void { - const event: BaseEventInterface = this.__initializeEventObj(eventName, options); + const event: BaseEventInterface = this.__initializeEventObj( + eventName, + options + ); const middlewares = options.middlewares ?? []; if (middlewares.length > 0) { @@ -349,82 +300,6 @@ class BaseEventEmitter logger.log(LogLevel.INFO, `Event initialized: "${eventName}"`, baseEvent); return baseEvent; } - - - /** - * #### Description - * The `__listenToEvent` method is a private listener method within the `BaseEventListener` class that listens to - * a specified event and allows middleware processing before handling the event data. - * - * #### Purpose - * This method enables event listening within `BaseEventListener`, supporting middleware-based pre-processing - * of events before they reach the main handler. - * - * #### Events - * Subscribes to the specified event and applies middleware before handling. - * - * #### Parameters - * - `eventName: string` - The event name to listen for. - * - `options: { handler: (event: BaseEventInterface) => void, middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false> }` - * - **handler** - Function that handles the processed event. - * - **middlewares** - Optional array of middleware functions for processing the event before it reaches the handler. - * - * #### Requirements - * - `eventName` must be a valid string. - * - `handler` must be a function that processes the event data. - * - If `middlewares` are provided, they should be functions that accept an event and a `next` function. - * - * #### Returns - * - `void` - This method does not return a value. - * - * #### Usage - * Use this method to listen to events within the `BaseEventListener` and apply middleware before passing them - * to the handler. - * - * @param {string} eventName - The event name to listen for. - * @param {object} options - Configuration object containing the handler and optional middleware functions. - * - * @example - * ```typescript - * listener.__listenToEvent("room:updated", { - * handler: (event) => { console.log("Event received:", event); }, - * middlewares: [ - * (event, next) => { event.data.timestamp = Date.now(); next(); }, - * (event, next) => { if (event.data.isValid) next(); else console.log("Invalid event data"); } - * ] - * }); - * ``` - */ -private __listenToEvent( - eventName: string, - options: { - handler: (event: BaseEventInterface) => void; - middlewares?: Array<(event: BaseEventInterface, next: () => void) => void | false>; - } -): void { - const middlewares = options.middlewares ?? []; - const handler = options.handler; - - // Register the event listener - this.on(eventName, (event: BaseEventInterface) => { - if (middlewares.length > 0) { - // Middleware processing - const processMiddlewares = (index: number) => { - if (index < middlewares.length) { - middlewares[index](event, () => processMiddlewares(index + 1)); - } else { - handler(event); - logger.log(LogLevel.INFO, `Event handled: "${eventName}"`, event); - } - }; - processMiddlewares(0); - } else { - // Directly invoke handler if no middleware - handler(event); - logger.log(LogLevel.INFO, `Event handled: "${eventName}"`, event); - } - }); -} } export { BaseEventEmitter }; From c7bde77faf3259bc7100dd8c5a355ed17ab3a668 Mon Sep 17 00:00:00 2001 From: Astitv Singh Date: Sat, 9 Nov 2024 21:18:11 +0530 Subject: [PATCH 08/11] `Commit Message Title` `Summary` A brief one-line summary of the changes made in this commit. `Description` A detailed description of the changes introduced by this commit. Include information about why the changes were made, how they address specific issues or requirements, and any relevant context or considerations. `Type` Specify the type of change represented by this commit. Choose only one of the following options: - Feature: A new feature or enhancement added to the project. - Fix: A bug fix or resolution to an issue. - Refactor: Code refactoring or restructuring without changing behavior. - Documentation: Updates or additions to documentation files. - Test: Additions or modifications to tests. - Chore: Routine maintenance tasks, such as dependency updates or code cleanup. `Impact` Describe the impact of this change on the project. Consider factors such as functionality, performance, compatibility, and user experience. `Related Issues` List any related issues or tickets addressed by this commit. Use GitHub issue numbers or links to reference specific issues. `Dependencies` Specify any dependencies or requirements associated with this commit. Include information about libraries, frameworks, or other components affected by the changes. `Testing` Describe the testing approach or strategy used to validate this change. Include details about test cases, scenarios, or environments used for testing. `Notes` Add any additional notes, comments, or considerations relevant to this commit. This may include warnings, caveats, or follow-up tasks for future work. `Commit Checklist`: - [ ] The commit message follows the established format and guidelines. - [ ] The changes introduced by the commit have been thoroughly reviewed and tested. - [ ] Any related issues or tickets have been appropriately linked or referenced. - [ ] Documentation has been updated to reflect the changes introduced by the commit. - [ ] The commit does not introduce any new linting errors, warnings, or regressions. `Branch` On branch `Changes` Changes to be committed: --- src/models/pokerTable/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index 7ce6cbf..d2d8578 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -157,7 +157,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * console.log(table.getBigBlind()); // Console Output: 10 * ``` */ - private __bigBlindAmount: number = this.__smallBlind * 2; + private __bigBlindAmount: number = this.getSmallBlind() * 2; /** * @property {PokerSeatInterface[]} __seats From 7d6c2c824b6e618c2435d0105ec903e9bde7c24a Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Thu, 14 Nov 2024 22:26:08 +0300 Subject: [PATCH 09/11] Implement Assign Roles Method in PokerTable Class --- src/enums/events/pokerSeat/index.ts | 41 +++++++- src/interfaces/pokerPlayer/index.ts | 3 + src/interfaces/pokerSeat/index.ts | 13 ++- src/models/pokerSeat/index.ts | 145 +++++++++++++++++++++++++++ src/models/pokerTable/index.ts | 150 ++++++++++++++++++++++++---- 5 files changed, 330 insertions(+), 22 deletions(-) diff --git a/src/enums/events/pokerSeat/index.ts b/src/enums/events/pokerSeat/index.ts index fa8906a..2606abd 100644 --- a/src/enums/events/pokerSeat/index.ts +++ b/src/enums/events/pokerSeat/index.ts @@ -1,3 +1,4 @@ + //@collapse /** @@ -66,4 +67,42 @@ enum PokerSeatEvents { VACATED = "PokerSeat:Vacated", } -export { PokerSeatEvents }; +enum PokerSeatRoles { + /** + * Indicates that the seat has been initialized and is ready for occupancy. + * + * @example + * ```typescript + * const seatEvent: PokerSeatEvents = PokerSeatEvents.INITIALIZED; + * console.log(seatEvent); + * // Console Output: "PokerSeat:Initialized" + * ``` + */ + DEALER = "PokerSeat:Dealer", + + /** + * Indicates a seat has been occupied by a player. + * + * @example + * ```typescript + * const seatEvent: PokerSeatEvents = PokerSeatEvents.OCCUPIED; + * console.log(seatEvent); + * // Console Output: "PokerSeat:Occupied" + * ``` + */ + SMALLBLIND = "PokerSeat:SmallBlind", + + /** + * Indicates a seat has been vacated by a player. + * + * @example + * ```typescript + * const seatEvent: PokerSeatEvents = PokerSeatEvents.VACATED; + * console.log(seatEvent); + * // Console Output: "PokerSeat:Vacated" + * ``` + */ + BIGBLIND = "PokerSeat:BigBlind", +} + +export { PokerSeatEvents , PokerSeatRoles}; diff --git a/src/interfaces/pokerPlayer/index.ts b/src/interfaces/pokerPlayer/index.ts index 9b558d3..ecbf7e5 100644 --- a/src/interfaces/pokerPlayer/index.ts +++ b/src/interfaces/pokerPlayer/index.ts @@ -1,3 +1,4 @@ + //@collapse import { BaseEventEmitterInterface } from "../_base"; @@ -66,6 +67,8 @@ interface PokerPlayerInterface extends BaseEventEmitterInterface { */ getId(): string; + getChips():number; + bet(amount: number): boolean; setIsFolded(bool: boolean): boolean; diff --git a/src/interfaces/pokerSeat/index.ts b/src/interfaces/pokerSeat/index.ts index 0ab8861..f452821 100644 --- a/src/interfaces/pokerSeat/index.ts +++ b/src/interfaces/pokerSeat/index.ts @@ -1,4 +1,7 @@ -//collapse + + + +//@collapse import { BaseEventEmitterInterface } from "../_base"; import { PokerPlayerInterface } from "../pokerPlayer"; @@ -18,7 +21,7 @@ interface PokerSeatConfig { * @property {number} position * The maximum number of players that can be seated at the PokerTable[2-14]. */ - position: number; + position?: number; /** * @property {boolean} isDealer @@ -31,6 +34,8 @@ interface PokerSeatConfig { * The maximum number of players that can be seated at the PokerTable[2-14]. */ player?: PokerPlayerInterface; + + role?:string[]; } /** @@ -110,6 +115,10 @@ interface PokerSeatInterface extends BaseEventEmitterInterface { */ getPlayer(): PokerPlayerInterface | undefined; + getRole(): string[]; + + addRole(role:string): string[]; + /************************************************************************************************************** * UPDATE METHODS (MODIFYING EXISTING OBJECTS) **************************************************************************************************************/ diff --git a/src/models/pokerSeat/index.ts b/src/models/pokerSeat/index.ts index 3c55b74..78813b6 100644 --- a/src/models/pokerSeat/index.ts +++ b/src/models/pokerSeat/index.ts @@ -166,6 +166,8 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { */ private __player: PokerPlayerInterface | undefined = undefined; + private __role! : string[] ; + /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS **************************************************************************************************************/ @@ -283,6 +285,11 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { config.player ? this.__setPlayer(config.player) : this.__setPlayer(this.__player); + + // Assign a player to the seat if provided; otherwise, seat remains unoccupied. + config.role + ? this.__setRole(config.role) + : this.__setRole(this.__role); } // Emit `INITIALIZED` event after initialization @@ -533,6 +540,94 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { return this.__player; } + /** + * #### Description + * The `getPlayer` method is a public getter that retrieves the player occupying this seat, if any. + * + * #### Implements + * N/A + * + * #### Overrides + * N/A + * + * #### Purpose + * This method provides access to the player currently occupying the seat, allowing the application to retrieve + * player-specific data, manage player actions, or determine seat vacancy. + * + * #### Events + * N/A + * + * #### Parameters + * N/A + * + * #### Requirements + * - This method requires no parameters. + * + * #### Returns + * - `PokerPlayerInterface | undefined` - Returns the player instance occupying this seat, or `undefined` if the seat is vacant. + * + * #### Usage + * Use this method to retrieve the player occupying this seat, which is helpful in managing player actions or + * determining if the seat is available for another player. + * + * @returns {PokerPlayerInterface | undefined} - The player instance if occupied, or `undefined` if vacant. + * + * @example + * ```typescript + * const pokerSeat = new PokerSeat(); + * pokerSeat.occupySeat(player); // player implements PokerPlayerInterface + * console.log(pokerSeat.getPlayer()); + * // Console Output: + * ``` + */ + public getRole(): string[] { + return this.__role; + } + + /** + * #### Description + * The `getPlayer` method is a public getter that retrieves the player occupying this seat, if any. + * + * #### Implements + * N/A + * + * #### Overrides + * N/A + * + * #### Purpose + * This method provides access to the player currently occupying the seat, allowing the application to retrieve + * player-specific data, manage player actions, or determine seat vacancy. + * + * #### Events + * N/A + * + * #### Parameters + * N/A + * + * #### Requirements + * - This method requires no parameters. + * + * #### Returns + * - `PokerPlayerInterface | undefined` - Returns the player instance occupying this seat, or `undefined` if the seat is vacant. + * + * #### Usage + * Use this method to retrieve the player occupying this seat, which is helpful in managing player actions or + * determining if the seat is available for another player. + * + * @returns {PokerPlayerInterface | undefined} - The player instance if occupied, or `undefined` if vacant. + * + * @example + * ```typescript + * const pokerSeat = new PokerSeat(); + * pokerSeat.occupySeat(player); // player implements PokerPlayerInterface + * console.log(pokerSeat.getPlayer()); + * // Console Output: + * ``` + */ + public addRole(role:string): string[] { + return this.__addRole(role); + } + /************************************************************************************************************** * UPDATE METHODS (MODIFYING EXISTING OBJECTS) **************************************************************************************************************/ @@ -802,6 +897,56 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { return this.__player; } + /** + * #### Description + * The `__setPlayer` method assigns a player to this `PokerSeat`. + * + * #### Purpose + * This method designates a player to occupy the seat or clears the seat if set to `undefined`, allowing for + * seat availability management. + * + * #### Implements + * N/A + * + * #### Overrides + * N/A + * + * #### Parameters + * - `player: PokerPlayerInterface | undefined` - The player instance to be assigned to the seat, or `undefined` to mark the seat vacant. + * + * #### Requirements + * - `player` must be an instance of `PokerPlayerInterface`, or `undefined` to vacate the seat. + * + * #### Returns + * - `PokerPlayerInterface | undefined` - The player occupying the seat or `undefined` if vacant. + * + * #### Usage + * This method is used internally to assign a player to the seat or clear the seat. + * + * @param {PokerPlayerInterface | undefined} player - The player to occupy the seat, or `undefined` if no player is assigned. + * + * @returns {PokerPlayerInterface | undefined} - The player instance or `undefined` after assignment. + * + * @example + * ```typescript + * const pokerSeat = new PokerSeat(); + * pokerSeat.__setPlayer(playerInstance); + * console.log(pokerSeat.getPlayer()); + * // Console Output: + * ``` + */ + private __setRole( + role: string[] + ): string[]{ + this.__role = role; + return this.__role; + } + + private __addRole(role: string): string[] { + this.__role.push(role); + return this.getRole(); + } + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index d2d8578..a3608f1 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -6,6 +6,7 @@ import { LogLevel, Source, PokerTableEvents, + PokerSeatRoles, } from "../../enums"; // Import Interfaces @@ -18,6 +19,7 @@ import { BaseEventInterface, PokerGameInterface, PokerGameConfig, + PokerSeatConfig, } from "../../interfaces"; // Import Models @@ -28,6 +30,7 @@ import { PokerSeat } from "../pokerSeat"; // Import Utils import { generateUniqueId, logger } from "../../utils"; import { PokerGame } from "../pokerGame"; +import { exit } from "process"; /** * @class `PokerTable` @@ -157,7 +160,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { * console.log(table.getBigBlind()); // Console Output: 10 * ``` */ - private __bigBlindAmount: number = this.getSmallBlind() * 2; + private __bigBlindAmount: number = this.__smallBlind * 2; /** * @property {PokerSeatInterface[]} __seats @@ -309,23 +312,9 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__seatOccupancyUpdateEventHandler(); }); - // // seat.on(PokerSeatEvents.OCCUPIED,(event)=>{}) - // seat.listenToEvent(PokerSeatEvents.OCCUPIED, { - // handler: (event: BaseEventInterface) => { - // this.__startGame(event); - // }, - // middlewares: [ - // (event, next) => { - // this.__checkIfGameInProgress(event, next); - // }, - // (event, next) => { - // this.__checkOccupancyCount(event, next); - // }, - // (event, next) => { - // this.__createGamePlayersList(event, next); - // }, - // ], - // }); + seat.on(PokerSeatEvents.VACATED, (event) => { + this.__seatVacatedUpdateEventHandler(); + }); } } } @@ -700,6 +689,61 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } + private __assignRoles(event: BaseEventInterface,next: () => void): void | false { + + if (event.occupancyCount === 2) { + let foundDealer = false; + // Iterate over each seat to find the minimum occupied seat position + for (let i = 0; i < this.getSeats().length; i++) { + let seat = this.getSeats()[i]; + + // Check if the seat is occupied + if (seat.isOccupied()) { + if (!foundDealer) { + // First occupied seat gets DEALER and SMALLBLIND roles + seat.addRole(PokerSeatRoles.DEALER); + seat.addRole(PokerSeatRoles.SMALLBLIND); + foundDealer = true; + } else { + // Next occupied seat gets BIGBLIND role + seat.addRole(PokerSeatRoles.BIGBLIND); + break; // Exit loop after assigning BIGBLIND + } + } + } + } + + else if (event.occupancyCount > 2) { + const seats = this.getSeats(); + let dealerAssigned = false; + let smallBlindAssigned = false; + let bigBlindAssigned = false; + + for (let i = 0; i < seats.length; i++) { + let seat = seats[i]; + + // Check if the seat is occupied + if (seat.isOccupied()) { + if (!dealerAssigned) { + // First occupied seat gets DEALER role + seat.addRole(PokerSeatRoles.DEALER); + dealerAssigned = true; + } else if (!smallBlindAssigned) { + // Next occupied seat after DEALER gets SMALLBLIND role + seat.addRole(PokerSeatRoles.SMALLBLIND); + smallBlindAssigned = true; + } else if (!bigBlindAssigned) { + // Next occupied seat after SMALLBLIND gets BIGBLIND role + seat.addRole(PokerSeatRoles.BIGBLIND); + bigBlindAssigned = true; + break; // Exit loop after assigning BIGBLIND + } + } + } + } + next(); + } + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. @@ -725,7 +769,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { event.lastModifiedAt = new Date(); next(); } - + private __checkOccupancyCount( event: BaseEventInterface, next: () => void @@ -751,6 +795,35 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { next(); } + private __validatePlayerBalances(event: BaseEventInterface, next: () => void): void | false { + const bigBlind = this.getBigBlind(); + + // Loop through each seat to check player balances + for (let seat of this.getSeats()) { + const player = seat.getPlayer(); + + // If the seat is occupied, check the player's balance + if (player) { + const playerBalance = player.getChips(); + + if (playerBalance < bigBlind) { + // Log a warning if a player has insufficient funds and halt the game initialization + logger.log( + LogLevel.WARN, + `${Source.POKER_TABLE}: Player ${player.getId()} has insufficient balance (${playerBalance}). Minimum required is ${bigBlind}.`, + { tableId: this.getId(), playerId: player.getId(), requiredBalance: bigBlind } + ) + + return false; + } + } + } + + // If all players have sufficient balance, proceed to the next middleware + event.lastModifiedAt = new Date(); + next(); + } + private __createGamePlayersList( event: BaseEventInterface, next: () => void @@ -817,8 +890,47 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { (event, next) => { this.__checkOccupancyCount(event, next); }, + (event, next) => { + this.__assignRoles(event, next); + }, + (event, next) => { + this.__validatePlayerBalances(event, next); + }, + (event, next) => { + this.__createGamePlayersList(event, next); + }, + (event) => { + this.__startGame(event); + }, + ], + }); + } + + private __seatVacatedUpdateEventHandler(event?: BaseEventInterface): void { + this.emitEvent(PokerTableEvents.NEW_GAME, { + event: { source: Source.POKER_TABLE, data: { tableId: this.getId() } }, + middlewares: [ + (event, next) => { + this.__checkIfGameInProgress(event, next); + }, + (event, next) => { + this.__checkOccupancyCount(event, next); + }, + (event, next) => { + this.__assignRoles(event, next); + }, + (event, next) => { + this.__validatePlayerBalances(event, next); + }, + (event, next) => { + this.__createGamePlayersList(event, next); + }, + (event) => { + this.__startGame(event); + }, ], }); } + } export { PokerTable }; From 2a3fb551c399385e2f27005143d1c76c85c13bb1 Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Thu, 14 Nov 2024 23:08:16 +0300 Subject: [PATCH 10/11] Changed assignRole as a method --- src/models/pokerTable/index.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index a3608f1..7488f54 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -689,7 +689,11 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } - private __assignRoles(event: BaseEventInterface,next: () => void): void | false { + public assignRoles(event: BaseEventInterface): void | false { + this.__assignRoles(event); + } + + private __assignRoles(event: BaseEventInterface): void | false { if (event.occupancyCount === 2) { let foundDealer = false; @@ -741,9 +745,15 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { } } } - next(); } + private __assignRolesMiddleware(event: BaseEventInterface,next: () => void): void | false { + + return this.__assignRoles(event); + next(); + } + + /** * #### Description * Checks seat availability to determine if it can be occupied by a player. @@ -891,7 +901,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__checkOccupancyCount(event, next); }, (event, next) => { - this.__assignRoles(event, next); + this.__assignRolesMiddleware(event, next); }, (event, next) => { this.__validatePlayerBalances(event, next); @@ -917,7 +927,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { this.__checkOccupancyCount(event, next); }, (event, next) => { - this.__assignRoles(event, next); + this.__assignRolesMiddleware(event, next); }, (event, next) => { this.__validatePlayerBalances(event, next); From 83af847f0b69b118898b6d81dbf2adddd6d1c83a Mon Sep 17 00:00:00 2001 From: anshulrastogi9 Date: Fri, 15 Nov 2024 06:44:30 +0300 Subject: [PATCH 11/11] fixed addRole middleware --- src/interfaces/pokerSeat/index.ts | 2 +- src/models/pokerSeat/index.ts | 20 +++++----- src/models/pokerTable/index.ts | 65 +++++++++++-------------------- 3 files changed, 33 insertions(+), 54 deletions(-) diff --git a/src/interfaces/pokerSeat/index.ts b/src/interfaces/pokerSeat/index.ts index f452821..a2d19ab 100644 --- a/src/interfaces/pokerSeat/index.ts +++ b/src/interfaces/pokerSeat/index.ts @@ -115,7 +115,7 @@ interface PokerSeatInterface extends BaseEventEmitterInterface { */ getPlayer(): PokerPlayerInterface | undefined; - getRole(): string[]; + getRoles(): string[]; addRole(role:string): string[]; diff --git a/src/models/pokerSeat/index.ts b/src/models/pokerSeat/index.ts index 78813b6..7015e64 100644 --- a/src/models/pokerSeat/index.ts +++ b/src/models/pokerSeat/index.ts @@ -166,7 +166,7 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { */ private __player: PokerPlayerInterface | undefined = undefined; - private __role! : string[] ; + private __roles! : string[] ; /************************************************************************************************************** * CONSTRUCTOR & INITIALIZERS @@ -288,8 +288,8 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { // Assign a player to the seat if provided; otherwise, seat remains unoccupied. config.role - ? this.__setRole(config.role) - : this.__setRole(this.__role); + ? this.__setRoles(config.role) + : this.__setRoles(this.__roles); } // Emit `INITIALIZED` event after initialization @@ -580,8 +580,8 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { * // Console Output: * ``` */ - public getRole(): string[] { - return this.__role; + public getRoles(): string[] { + return this.__roles; } /** @@ -935,16 +935,16 @@ class PokerSeat extends BaseEventEmitter implements PokerSeatInterface { * // Console Output: * ``` */ - private __setRole( + private __setRoles( role: string[] ): string[]{ - this.__role = role; - return this.__role; + this.__roles = role; + return this.__roles; } private __addRole(role: string): string[] { - this.__role.push(role); - return this.getRole(); + this.__roles.push(role); + return this.getRoles(); } /** diff --git a/src/models/pokerTable/index.ts b/src/models/pokerTable/index.ts index 7488f54..6976409 100644 --- a/src/models/pokerTable/index.ts +++ b/src/models/pokerTable/index.ts @@ -313,7 +313,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); seat.on(PokerSeatEvents.VACATED, (event) => { - this.__seatVacatedUpdateEventHandler(); + this.__seatOccupancyUpdateEventHandler(); }); } } @@ -468,7 +468,18 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { /************************************************************************************************************** * WRAPPER METHODS (UTILITY & CONVENIENCE) **************************************************************************************************************/ + public occupancyCount():number{ + let occupiedSeats = 0; + + for (let i = 0; i < this.getSeats().length; i++) { + let seat = this.getSeats()[i]; + if (seat.getPlayer()) { + occupiedSeats += 1; + } + } + return occupiedSeats; + } /** * `size` * Starts a new PokerGame if there are at least two active players at the PokerTable. @@ -689,13 +700,13 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { return false; } - public assignRoles(event: BaseEventInterface): void | false { - this.__assignRoles(event); + public assignRoles(): void | false { + this.__assignRoles(); } - private __assignRoles(event: BaseEventInterface): void | false { + private __assignRoles(): void | false { - if (event.occupancyCount === 2) { + if (this.occupancyCount()===2) { let foundDealer = false; // Iterate over each seat to find the minimum occupied seat position for (let i = 0; i < this.getSeats().length; i++) { @@ -717,7 +728,7 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { } } - else if (event.occupancyCount > 2) { + else if (this.occupancyCount()>2) { const seats = this.getSeats(); let dealerAssigned = false; let smallBlindAssigned = false; @@ -748,9 +759,8 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { } private __assignRolesMiddleware(event: BaseEventInterface,next: () => void): void | false { - - return this.__assignRoles(event); - next(); + this.__assignRoles(); + next(); } @@ -779,19 +789,14 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { event.lastModifiedAt = new Date(); next(); } + + private __checkOccupancyCount( event: BaseEventInterface, next: () => void ): void | false { - let occupiedSeats = 0; - - for (let i = 0; i < this.getSeats().length; i++) { - let seat = this.getSeats()[i]; - if (seat.getPlayer()) { - occupiedSeats += 1; - } - } + let occupiedSeats = this.occupancyCount(); // Check if all seats are occupied if (occupiedSeats === this.getSeats().length) { @@ -916,31 +921,5 @@ class PokerTable extends BaseEventEmitter implements PokerTableInterface { }); } - private __seatVacatedUpdateEventHandler(event?: BaseEventInterface): void { - this.emitEvent(PokerTableEvents.NEW_GAME, { - event: { source: Source.POKER_TABLE, data: { tableId: this.getId() } }, - middlewares: [ - (event, next) => { - this.__checkIfGameInProgress(event, next); - }, - (event, next) => { - this.__checkOccupancyCount(event, next); - }, - (event, next) => { - this.__assignRolesMiddleware(event, next); - }, - (event, next) => { - this.__validatePlayerBalances(event, next); - }, - (event, next) => { - this.__createGamePlayersList(event, next); - }, - (event) => { - this.__startGame(event); - }, - ], - }); - } - } export { PokerTable };