refactors to nested array
This commit is contained in:
parent
96dfc35b1e
commit
d0f6a3fdf2
5 changed files with 197 additions and 211 deletions
121
src/game/card.ts
121
src/game/card.ts
|
|
@ -1,77 +1,24 @@
|
|||
type CardValue = -2 | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
export type Card =
|
||||
| -2
|
||||
| -1
|
||||
| 0
|
||||
| 1
|
||||
| 2
|
||||
| 3
|
||||
| 4
|
||||
| 5
|
||||
| 6
|
||||
| 7
|
||||
| 8
|
||||
| 9
|
||||
| 10
|
||||
| 11
|
||||
| 12;
|
||||
|
||||
export type ObfuscatedCardValue = CardValue | "X";
|
||||
export type ConcealableCard = Card | null;
|
||||
|
||||
type CardColor =
|
||||
| "darkblue"
|
||||
| "lightblue"
|
||||
| "green"
|
||||
| "yellow"
|
||||
| "red"
|
||||
| "black";
|
||||
|
||||
// TODO: use smarter types like Omit<>, Pick<>, etc.
|
||||
export type ObfuscatedCard = {
|
||||
id: number;
|
||||
name: string;
|
||||
value: ObfuscatedCardValue;
|
||||
color: CardColor;
|
||||
};
|
||||
|
||||
export class Card {
|
||||
id: number;
|
||||
name: string;
|
||||
value: CardValue;
|
||||
color: CardColor;
|
||||
constructor(id: number, value: CardValue) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
this.name = `${value} Card`;
|
||||
this.color = this.matchColorToCardValue(value);
|
||||
}
|
||||
|
||||
matchColorToCardValue(value: CardValue | ObfuscatedCardValue): CardColor {
|
||||
switch (value) {
|
||||
case -2:
|
||||
return "darkblue";
|
||||
case -1:
|
||||
return "darkblue";
|
||||
case 0:
|
||||
return "lightblue";
|
||||
case 1:
|
||||
return "green";
|
||||
case 2:
|
||||
return "green";
|
||||
case 3:
|
||||
return "green";
|
||||
case 4:
|
||||
return "green";
|
||||
case 5:
|
||||
return "yellow";
|
||||
case 6:
|
||||
return "yellow";
|
||||
case 7:
|
||||
return "yellow";
|
||||
case 8:
|
||||
return "yellow";
|
||||
case 9:
|
||||
return "red";
|
||||
case 10:
|
||||
return "red";
|
||||
case 11:
|
||||
return "red";
|
||||
case 12:
|
||||
return "red";
|
||||
case "X":
|
||||
return "black";
|
||||
default:
|
||||
return "red";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type ObfuscatedCardStack = {
|
||||
cards: ObfuscatedCard[];
|
||||
export type ConcealableCardStack = {
|
||||
cards: ConcealableCard[];
|
||||
};
|
||||
|
||||
export class CardStack {
|
||||
|
|
@ -84,77 +31,77 @@ export class CardStack {
|
|||
generateCards() {
|
||||
for (let cardNumber = 1; cardNumber <= 150; cardNumber++) {
|
||||
if (cardNumber <= 5) {
|
||||
this.cards.push(new Card(cardNumber, -2));
|
||||
this.cards.push(-2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 5 && cardNumber <= 15) {
|
||||
this.cards.push(new Card(cardNumber, -1));
|
||||
this.cards.push(-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 15 && cardNumber <= 30) {
|
||||
this.cards.push(new Card(cardNumber, 0));
|
||||
this.cards.push(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 30 && cardNumber <= 40) {
|
||||
this.cards.push(new Card(cardNumber, 1));
|
||||
this.cards.push(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 40 && cardNumber <= 50) {
|
||||
this.cards.push(new Card(cardNumber, 2));
|
||||
this.cards.push(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 50 && cardNumber <= 60) {
|
||||
this.cards.push(new Card(cardNumber, 3));
|
||||
this.cards.push(3);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 60 && cardNumber <= 70) {
|
||||
this.cards.push(new Card(cardNumber, 4));
|
||||
this.cards.push(4);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 70 && cardNumber <= 80) {
|
||||
this.cards.push(new Card(cardNumber, 5));
|
||||
this.cards.push(5);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 80 && cardNumber <= 90) {
|
||||
this.cards.push(new Card(cardNumber, 6));
|
||||
this.cards.push(6);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 90 && cardNumber <= 100) {
|
||||
this.cards.push(new Card(cardNumber, 7));
|
||||
this.cards.push(7);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 100 && cardNumber <= 110) {
|
||||
this.cards.push(new Card(cardNumber, 8));
|
||||
this.cards.push(8);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 110 && cardNumber <= 120) {
|
||||
this.cards.push(new Card(cardNumber, 9));
|
||||
this.cards.push(9);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 120 && cardNumber <= 130) {
|
||||
this.cards.push(new Card(cardNumber, 10));
|
||||
this.cards.push(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 130 && cardNumber <= 140) {
|
||||
this.cards.push(new Card(cardNumber, 11));
|
||||
this.cards.push(11);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cardNumber > 140 && cardNumber <= 150) {
|
||||
this.cards.push(new Card(cardNumber, 12));
|
||||
this.cards.push(12);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,27 @@ import { Game } from "./game";
|
|||
|
||||
import { allGames } from "./game";
|
||||
|
||||
export const handleJoinSession = (socket: Socket, sessionId: string) => {
|
||||
type SessionResponse = "success" | "error:full" | "error:running";
|
||||
|
||||
export const handleJoinSession = (
|
||||
socket: Socket,
|
||||
sessionId: string,
|
||||
callback: Function
|
||||
) => {
|
||||
const isSessionRunning = allGames.some(
|
||||
(game) => game.sessionId === sessionId
|
||||
);
|
||||
if (isSessionRunning) {
|
||||
callback("error:running" satisfies SessionResponse);
|
||||
socket.emit(
|
||||
"message",
|
||||
"A Game is already running in this session. Please join another session."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
socket.join(sessionId);
|
||||
callback("success" satisfies SessionResponse);
|
||||
console.log("User joined session:", sessionId);
|
||||
|
||||
const numberOfClients = io.sockets.adapter.rooms.get(sessionId)?.size ?? 0;
|
||||
|
|
@ -41,6 +60,7 @@ export const handleNewGame = (
|
|||
|
||||
if (players && players.size > 1) {
|
||||
const game = new Game(socket, sessionId, players);
|
||||
removeOldGame(sessionId);
|
||||
allGames.push(game);
|
||||
console.log(`New Game created with ${game.playerCount} players!`);
|
||||
game.gameLoop();
|
||||
|
|
@ -62,3 +82,12 @@ export const handleDisconnect = (socket: Socket) => {
|
|||
io.to(sessionName).emit("clients-in-session", socketIds.size);
|
||||
});
|
||||
};
|
||||
|
||||
const removeOldGame = (sessionId: string) => {
|
||||
const oldGameIndex = allGames.findIndex(
|
||||
(game) => game.sessionId === sessionId
|
||||
);
|
||||
if (oldGameIndex !== -1) {
|
||||
allGames.splice(oldGameIndex, 1);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
121
src/game/game.ts
121
src/game/game.ts
|
|
@ -1,6 +1,6 @@
|
|||
import { Player, ObfuscatedPlayer } from "./player";
|
||||
import { CardStack } from "./card";
|
||||
import { Card, ObfuscatedCardStack } from "./card";
|
||||
import { Player, ObfuscatedPlayer, ConcealableColumn } from "./player";
|
||||
import { CardStack, ConcealableCard } from "./card";
|
||||
import { Card, ConcealableCardStack } from "./card";
|
||||
import { Socket } from "socket.io";
|
||||
import { io } from "../server";
|
||||
|
||||
|
|
@ -18,14 +18,14 @@ type PlayerAction<ActionDataType> = {
|
|||
data: ActionDataType;
|
||||
};
|
||||
|
||||
type CardPosition = number;
|
||||
type CardPosition = [number, number];
|
||||
|
||||
// obfuscated types are used to send only necessary data to the client
|
||||
export type ObfuscatedGame = {
|
||||
sessionId: string;
|
||||
playerCount: number;
|
||||
players: ObfuscatedPlayer[];
|
||||
cardStack: ObfuscatedCardStack;
|
||||
cardStack: ConcealableCardStack;
|
||||
discardPile: Card[];
|
||||
phase: string;
|
||||
round: number;
|
||||
|
|
@ -78,13 +78,8 @@ export class Game {
|
|||
let index = 0;
|
||||
playerIds.forEach((socketId) => {
|
||||
index++;
|
||||
const playerCards = cardStack.cards.splice(0, 12);
|
||||
const player = new Player(
|
||||
index,
|
||||
socketId,
|
||||
`Player ${index}`,
|
||||
playerCards
|
||||
);
|
||||
|
||||
const player = new Player(index, socketId, `Player ${index}`, cardStack);
|
||||
players.push(player);
|
||||
});
|
||||
|
||||
|
|
@ -98,8 +93,8 @@ export class Game {
|
|||
this.cardStack = new CardStack();
|
||||
this.cardStack.shuffleCards();
|
||||
this.players.forEach((player) => {
|
||||
player.cards = this.cardStack.cards.splice(0, 12);
|
||||
player.knownCardPositions = new Array(12).fill(false);
|
||||
player.deck = player.generateDeck(this.cardStack);
|
||||
player.knownCardPositions = player.createUnknownCardPositions();
|
||||
player.playersTurn = true;
|
||||
player.cardCache = null;
|
||||
player.tookDispiledCard = false;
|
||||
|
|
@ -117,6 +112,7 @@ export class Game {
|
|||
this.sendObfuscatedGameUpdate();
|
||||
while (this.phase !== gamePhase.gameEnded) {
|
||||
this.checkForFullRevealedCards();
|
||||
this.removeThreeOfAKinds();
|
||||
switch (this.phase) {
|
||||
case gamePhase.revealTwoCards:
|
||||
console.log("\nGame phase: revealTwoCards");
|
||||
|
|
@ -245,12 +241,15 @@ export class Game {
|
|||
|
||||
// Player Action Callbacks
|
||||
|
||||
revealCardAction(playerSocketId: string, cardPosition: number) {
|
||||
revealCardAction(playerSocketId: string, cardPosition: CardPosition) {
|
||||
const player = this.getPlayerBySocketId(playerSocketId);
|
||||
const revealedCard = player.cards[cardPosition];
|
||||
console.log(`Revealed card ${revealedCard} at position ${cardPosition}`);
|
||||
const [columnIndex, cardIndex] = cardPosition;
|
||||
const revealedCard = player.deck[columnIndex][cardIndex];
|
||||
console.log(
|
||||
`Revealed card ${revealedCard} at column ${columnIndex} card ${cardIndex}`
|
||||
);
|
||||
const playerIndex = this.players.indexOf(player!);
|
||||
this.players[playerIndex].knownCardPositions[cardPosition] = true;
|
||||
this.players[playerIndex].knownCardPositions[columnIndex][cardIndex] = true;
|
||||
this.sendObfuscatedGameUpdate();
|
||||
}
|
||||
|
||||
|
|
@ -281,15 +280,17 @@ export class Game {
|
|||
this.sendObfuscatedGameUpdate();
|
||||
}
|
||||
|
||||
placeCardAction(playerSocketId: string, cardPosition: number) {
|
||||
placeCardAction(playerSocketId: string, cardPosition: CardPosition) {
|
||||
const player = this.getPlayerBySocketId(playerSocketId);
|
||||
console.log(`Player ${player.name} placed a card.`);
|
||||
const placedCard = player.cardCache!;
|
||||
player.cardCache = null;
|
||||
const replacedCard = player.cards[cardPosition];
|
||||
const [columnIndex, cardIndex] = cardPosition;
|
||||
const replacedCard = player.deck[columnIndex][cardIndex];
|
||||
this.discardPile.push(replacedCard);
|
||||
player.cards[cardPosition] = placedCard;
|
||||
player.knownCardPositions[cardPosition] = true;
|
||||
player.deck[columnIndex][cardIndex] = placedCard;
|
||||
player.knownCardPositions[columnIndex][cardIndex] = true;
|
||||
// TODO: check for three of a kind
|
||||
this.nextPlayersTurn();
|
||||
this.phase = gamePhase.pickUpCard;
|
||||
this.sendObfuscatedGameUpdate();
|
||||
|
|
@ -379,32 +380,24 @@ export class Game {
|
|||
phase: this.phase,
|
||||
round: this.round,
|
||||
discardPile: this.discardPile,
|
||||
players: this.players.map(({ cards, ...player }) => {
|
||||
players: this.players.map(({ deck, ...player }) => {
|
||||
return {
|
||||
...player,
|
||||
cards: cards.map((card: Card, index: number) => {
|
||||
// unknown cards are obfuscated to X
|
||||
return {
|
||||
id: player.knownCardPositions[index] ? card.id : 0,
|
||||
value: player.knownCardPositions[index] ? card.value : "X",
|
||||
name: player.knownCardPositions[index]
|
||||
? card.name
|
||||
: "Facedown Card",
|
||||
color: player.knownCardPositions[index] ? card.color : "black",
|
||||
matchColorToCardValue: card.matchColorToCardValue,
|
||||
};
|
||||
deck: deck.map((column, columnIndex) => {
|
||||
const concealableColumn = column.map((card, cardIndex) => {
|
||||
// unknown cards are obfuscated to null
|
||||
return player.knownCardPositions[columnIndex][cardIndex]
|
||||
? card
|
||||
: (null as ConcealableCard);
|
||||
});
|
||||
return concealableColumn as ConcealableColumn;
|
||||
}),
|
||||
};
|
||||
} satisfies ObfuscatedPlayer;
|
||||
}),
|
||||
cardStack: {
|
||||
cards: this.cardStack.cards.map((card: Card) => {
|
||||
// player may not see the value of the facedown cards in the cardStack
|
||||
return {
|
||||
id: 0,
|
||||
value: "X",
|
||||
name: "Facedown Card",
|
||||
color: "black",
|
||||
};
|
||||
return null;
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
|
@ -419,13 +412,7 @@ export class Game {
|
|||
updatePlayerRoundPoints() {
|
||||
this.players.forEach((player) => {
|
||||
const revealedCardValuesSum = player.getRevealedCardsValueSum();
|
||||
const threeOfAKinds = player.getThreeOfAKinds();
|
||||
const threeOfAKindPoints = threeOfAKinds.reduce(
|
||||
(points, threeOfAKind) => points + threeOfAKind.value * 3,
|
||||
0
|
||||
);
|
||||
|
||||
player.roundPoints = revealedCardValuesSum - threeOfAKindPoints;
|
||||
player.roundPoints = revealedCardValuesSum;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -481,8 +468,8 @@ export class Game {
|
|||
if (alreadyClosedPlayers.length > 0) return; // TODO: check if this is correct with more than 2 players
|
||||
|
||||
const playerWithAllCardsRevealed = this.players.find((player) =>
|
||||
player.knownCardPositions.every(
|
||||
(knownCardPosition) => knownCardPosition === true
|
||||
player.knownCardPositions.every((knownCardsColumn) =>
|
||||
knownCardsColumn.every((knownCard) => knownCard === true)
|
||||
)
|
||||
);
|
||||
if (playerWithAllCardsRevealed) {
|
||||
|
|
@ -490,6 +477,22 @@ export class Game {
|
|||
}
|
||||
}
|
||||
|
||||
removeThreeOfAKinds() {
|
||||
this.players.forEach((player) => {
|
||||
const threeOfAKinds = player.getThreeOfAKinds();
|
||||
if (threeOfAKinds.length == 0) return;
|
||||
threeOfAKinds.forEach((threeOfAKind) => {
|
||||
const { columnIndex, value } = threeOfAKind;
|
||||
this.discardPile.push(value as Card);
|
||||
this.discardPile.push(value as Card);
|
||||
this.discardPile.push(value as Card);
|
||||
player.deck.splice(columnIndex, 1);
|
||||
player.knownCardPositions.splice(columnIndex, 1);
|
||||
});
|
||||
this.sendObfuscatedGameUpdate();
|
||||
});
|
||||
}
|
||||
|
||||
checkIfPointLimitReached() {
|
||||
const highestPoints = Math.max(
|
||||
...this.players.map((player) => player.totalPoints)
|
||||
|
|
@ -553,9 +556,11 @@ export class Game {
|
|||
|
||||
revealAllCards() {
|
||||
this.players.forEach((player) => {
|
||||
player.knownCardPositions = player.knownCardPositions.map(
|
||||
(knownCardPosition) => true
|
||||
);
|
||||
player.knownCardPositions.forEach((column, columnIndex) => {
|
||||
column.forEach((card, cardIndex) => {
|
||||
player.knownCardPositions[columnIndex][cardIndex] = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -650,16 +655,6 @@ export class Game {
|
|||
else throw new Error(`No player with socketId ${playerSocketId} found!`);
|
||||
}
|
||||
|
||||
listPlayerSocketListeners() {
|
||||
console.log("Player socket listeners:");
|
||||
io.sockets.sockets.forEach((socket) => {
|
||||
console.log(socket.id);
|
||||
socket.eventNames().forEach((eventName) => {
|
||||
console.log(`${eventName.toString()}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
sendMessageToAllPlayers(message: string) {
|
||||
io.to(this.sessionId).emit("message", message);
|
||||
console.log(`Sent Message (Session): ${message}`);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,30 @@
|
|||
import { Card, ObfuscatedCard } from "./card";
|
||||
import { Card, CardStack, ConcealableCard } from "./card";
|
||||
|
||||
type Column = [Card, Card, Card];
|
||||
type Deck = Column[];
|
||||
|
||||
export type ConcealableColumn = [
|
||||
ConcealableCard,
|
||||
ConcealableCard,
|
||||
ConcealableCard
|
||||
];
|
||||
type ConcealableDeck = ConcealableColumn[];
|
||||
|
||||
type ColumnIndex = number;
|
||||
|
||||
type ThreeOfAKind = {
|
||||
columnIndex: ColumnIndex;
|
||||
value: number;
|
||||
};
|
||||
|
||||
type KnownCardsColumn = [boolean, boolean, boolean];
|
||||
|
||||
export type ObfuscatedPlayer = {
|
||||
id: number;
|
||||
socketId: string;
|
||||
name: string;
|
||||
cards: ObfuscatedCard[];
|
||||
knownCardPositions: boolean[];
|
||||
deck: ConcealableDeck;
|
||||
knownCardPositions: KnownCardsColumn[];
|
||||
playersTurn: boolean;
|
||||
cardCache: Card | null;
|
||||
tookDispiledCard: boolean;
|
||||
|
|
@ -14,26 +33,12 @@ export type ObfuscatedPlayer = {
|
|||
closedRound: boolean;
|
||||
};
|
||||
|
||||
type ColumnPosition = [number, number, number];
|
||||
|
||||
type ThreeOfAKind = {
|
||||
position: ColumnPosition;
|
||||
value: number;
|
||||
};
|
||||
|
||||
const COLUMN_POSITIONS: ColumnPosition[] = [
|
||||
[0, 4, 8],
|
||||
[1, 5, 9],
|
||||
[2, 6, 10],
|
||||
[3, 7, 11],
|
||||
];
|
||||
|
||||
export class Player {
|
||||
id: number;
|
||||
socketId: string;
|
||||
name: string;
|
||||
cards: Card[];
|
||||
knownCardPositions: boolean[];
|
||||
deck: Deck;
|
||||
knownCardPositions: KnownCardsColumn[];
|
||||
playersTurn: boolean;
|
||||
cardCache: Card | null; // this is where the card is temporarily stored when a player draws a card
|
||||
tookDispiledCard: boolean; // this is used to check if a player took a dispiled card in the current turn
|
||||
|
|
@ -41,12 +46,17 @@ export class Player {
|
|||
totalPoints: number;
|
||||
closedRound: boolean;
|
||||
place: number | null; // indicates the place the player got in the last round
|
||||
constructor(id: number, socketId: string, name: string, cards: Card[]) {
|
||||
constructor(
|
||||
id: number,
|
||||
socketId: string,
|
||||
name: string,
|
||||
cardStack: CardStack
|
||||
) {
|
||||
this.id = id;
|
||||
this.socketId = socketId;
|
||||
this.name = name;
|
||||
this.cards = cards;
|
||||
this.knownCardPositions = new Array(12).fill(false);
|
||||
this.deck = this.generateDeck(cardStack);
|
||||
this.knownCardPositions = this.createUnknownCardPositions();
|
||||
this.playersTurn = true;
|
||||
this.cardCache = null;
|
||||
this.tookDispiledCard = false;
|
||||
|
|
@ -56,74 +66,79 @@ export class Player {
|
|||
this.place = null;
|
||||
}
|
||||
|
||||
generateDeck(cardStack: CardStack): Deck {
|
||||
const deck: Deck = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
deck.push(cardStack.cards.splice(0, 3) as Column);
|
||||
}
|
||||
return deck;
|
||||
}
|
||||
|
||||
createUnknownCardPositions(): KnownCardsColumn[] {
|
||||
const knownCardPositions: KnownCardsColumn[] = [];
|
||||
for (let i = 0; i < 4; i++) {
|
||||
knownCardPositions.push([false, false, false]);
|
||||
}
|
||||
return knownCardPositions;
|
||||
}
|
||||
|
||||
hasInitialCardsRevealed(): boolean {
|
||||
const revealedCards = this.knownCardPositions.filter(
|
||||
(knownCard) => knownCard === true
|
||||
const flattenedKnownCardPositions = this.knownCardPositions.flat();
|
||||
const revealedCards = flattenedKnownCardPositions.filter(
|
||||
(position) => position
|
||||
);
|
||||
if (revealedCards.length > 1) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
getRevealedCardCount(): number {
|
||||
return this.knownCardPositions.filter((position) => position).length;
|
||||
return this.knownCardPositions.flat().filter((position) => position == true)
|
||||
.length;
|
||||
}
|
||||
|
||||
getThreeOfAKinds(): ThreeOfAKind[] {
|
||||
const revealedCardPositions = this.getRevealedCardPositions();
|
||||
const columns: ColumnPosition[] = COLUMN_POSITIONS;
|
||||
const threeOfAKinds: ThreeOfAKind[] = [];
|
||||
columns.forEach((column) => {
|
||||
const columnValues = column.map((position) => this.cards[position].value);
|
||||
const columnHasSameValues = columnValues.every(
|
||||
(value) => value === columnValues[0]
|
||||
this.deck.forEach((column, index) => {
|
||||
const firstCard = column[0];
|
||||
const columnIndex = index;
|
||||
|
||||
const columnHasSameCards = column.every((card) => card === firstCard);
|
||||
const columnIsRevealed = this.knownCardPositions[columnIndex].every(
|
||||
(isCardRevealed) =>
|
||||
isCardRevealed === this.knownCardPositions[columnIndex][0]
|
||||
);
|
||||
const columnIsRevealed = column.every((position) =>
|
||||
revealedCardPositions.includes(position)
|
||||
);
|
||||
if (columnHasSameValues && columnIsRevealed) {
|
||||
|
||||
if (columnHasSameCards && columnIsRevealed) {
|
||||
threeOfAKinds.push({
|
||||
position: column,
|
||||
value: columnValues[0],
|
||||
columnIndex: columnIndex as ColumnIndex,
|
||||
value: firstCard,
|
||||
});
|
||||
}
|
||||
});
|
||||
return threeOfAKinds;
|
||||
}
|
||||
|
||||
getRevealedCardPositions(): number[] {
|
||||
const revealedCardPositions: number[] = [];
|
||||
this.knownCardPositions.forEach((position, index) => {
|
||||
if (position) revealedCardPositions.push(index);
|
||||
});
|
||||
return revealedCardPositions;
|
||||
}
|
||||
|
||||
getRevealedCards(): Card[] {
|
||||
const revealedCards: Card[] = [];
|
||||
this.knownCardPositions.forEach((position, index) => {
|
||||
if (position) revealedCards.push(this.cards[index]);
|
||||
this.knownCardPositions.forEach((column, columnIndex) => {
|
||||
column.forEach((isCardRevealed, cardIndex) => {
|
||||
if (isCardRevealed)
|
||||
revealedCards.push(this.deck[columnIndex][cardIndex]);
|
||||
});
|
||||
});
|
||||
return revealedCards;
|
||||
}
|
||||
|
||||
getRevealedCardsValueSum(): number {
|
||||
const revealedCards = this.getRevealedCards();
|
||||
const revealedCardsValueSum = revealedCards.reduce(
|
||||
(sum, card) => sum + card.value,
|
||||
0
|
||||
);
|
||||
let revealedCardsValueSum = 0;
|
||||
revealedCards.forEach((card) => (revealedCardsValueSum += card));
|
||||
return revealedCardsValueSum;
|
||||
}
|
||||
|
||||
getHighestRevealedCardValue(): number {
|
||||
const revealedCards = this.getRevealedCards();
|
||||
const highestRevealedCardValue = revealedCards.reduce(
|
||||
(highestValue, card) => {
|
||||
if (card.value > highestValue) return card.value;
|
||||
else return highestValue;
|
||||
},
|
||||
0
|
||||
);
|
||||
const highestRevealedCardValue = Math.max(...revealedCards);
|
||||
return highestRevealedCardValue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ export const io = new SocketIOServer(httpServer, {
|
|||
io.on("connection", (socket: Socket) => {
|
||||
console.log("A user connected:", socket.id);
|
||||
|
||||
socket.on("join-session", (sessionId: string) =>
|
||||
handleJoinSession(socket, sessionId)
|
||||
socket.on("join-session", (sessionId: string, callback) =>
|
||||
handleJoinSession(socket, sessionId, callback)
|
||||
);
|
||||
|
||||
socket.on("leave-session", (sessionId: string) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue