diff --git a/src/components/Game/Actions/PlayCard.tsx b/src/components/Game/Actions/PlayCard.tsx index 3f73c97..73fc46c 100644 --- a/src/components/Game/Actions/PlayCard.tsx +++ b/src/components/Game/Actions/PlayCard.tsx @@ -1,13 +1,7 @@ -import { useCallback, useMemo, useState } from "react" +import { useCallback, useEffect, useMemo, useState } from "react" import { useAppSelector } from "caches/hooks" -import { - getCardsWithoutBlanks, - getGameId, - getIsMyGo, - getRound, - getSelectedCards, -} from "caches/GameSlice" +import { getGame, getSelectedCards } from "caches/GameSlice" import { RoundStatus } from "model/Round" import { Button, @@ -21,16 +15,14 @@ import { } from "@mui/material" import { CardName } from "model/Cards" import { useGameActions } from "components/Hooks/useGameActions" +import { bestCardLead, getBestCard, getWorstCard } from "utils/GameUtils" type AutoPlayState = "off" | "best" | "worst" const PlayCard = () => { const theme = useTheme() const { playCard } = useGameActions() - const round = useAppSelector(getRound) - const gameId = useAppSelector(getGameId) - const myCards = useAppSelector(getCardsWithoutBlanks) - const isMyGo = useAppSelector(getIsMyGo) + const game = useAppSelector(getGame) const [autoPlay, setAutoPlay] = useState("off") const selectedCards = useAppSelector(getSelectedCards) @@ -72,14 +64,13 @@ const PlayCard = () => { const playButtonEnabled = useMemo( () => - isMyGo && - round && - round.status === RoundStatus.PLAYING && - round.completedHands.length + - myCards.filter(c => c.name !== CardName.EMPTY).length === + game.isMyGo && + game.round?.status === RoundStatus.PLAYING && + game.round.completedHands.length + + game.cardsFull.filter(c => c.name !== CardName.EMPTY).length === 5, - [isMyGo, round, myCards], + [game], ) const PlayCardButton = () => ( @@ -94,9 +85,25 @@ const PlayCard = () => { ) const selectCardToPlay = useCallback(() => { - if (selectedCards.length === 1 && gameId) - playCard({ gameId, card: selectedCards[0].name }) - }, [gameId, selectedCards]) + if (selectedCards.length === 1 && game.id) + playCard({ gameId: game.id, card: selectedCards[0].name }) + }, [game.id, selectedCards]) + + // Auto play logic + // 1. If best card lead or lead from bottom enabled, play worst card + // 2. If lead from the top enabled, play best card + useEffect(() => { + if (game.id && game.round?.suit && game.isMyGo) { + if (autoPlay === "worst" || bestCardLead(game.round)) { + const worstCard = getWorstCard(game.cardsFull, game.round) + if (worstCard) + playCard({ gameId: game.id, card: worstCard.name }) + } else if (autoPlay === "best") { + const bestCard = getBestCard(game.cardsFull, game.round) + if (bestCard) playCard({ gameId: game.id, card: bestCard.name }) + } + } + }, [playCard, autoPlay, game]) return ( diff --git a/src/utils/GameUtils.spec.ts b/src/utils/GameUtils.spec.ts index 7fb7d46..f061765 100644 --- a/src/utils/GameUtils.spec.ts +++ b/src/utils/GameUtils.spec.ts @@ -589,6 +589,11 @@ describe("GameUtils", () => { it("only one card left", () => { expect(getBestCard([CARDS.JOKER], ROUND)).toStrictEqual(CARDS.JOKER) }) + it("Hand with EMPTY cards", () => { + expect(getBestCard([EMPTY, ...HAND3], ROUND)).toStrictEqual( + CARDS.TWO_CLUBS, + ) + }) }) describe("canRenege", () => { diff --git a/src/utils/GameUtils.ts b/src/utils/GameUtils.ts index 14ec2ab..03af420 100644 --- a/src/utils/GameUtils.ts +++ b/src/utils/GameUtils.ts @@ -198,6 +198,9 @@ export const canRenege = (myCard: Card, cardLead: Card, suit: Suit) => { } export const getWorstCard = (cards: Card[], round: Round) => { + // Clear empty cards + cards = cards.filter(c => c.name !== CardName.EMPTY) + if (cards.length === 0) throw new Error("No cards to choose from") if (cards.length === 1) return cards[0] @@ -252,6 +255,9 @@ export const getWorstCard = (cards: Card[], round: Round) => { } export const getBestCard = (cards: Card[], round: Round) => { + // Clear empty cards + cards = cards.filter(c => c.name !== CardName.EMPTY) + if (cards.length === 0) throw new Error("No cards to choose from") if (cards.length === 1) return cards[0]