Skip to content

Commit

Permalink
Merge pull request #117 from daithihearn/feature/buy-cards-before-you…
Browse files Browse the repository at this point in the history
…r-go

Adding Keep Card button before it's your go
  • Loading branch information
daithihearn authored Feb 25, 2023
2 parents 288fafd + 280837f commit cb00d0a
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 108 deletions.
15 changes: 11 additions & 4 deletions src/caches/GameSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,23 @@ export const getIsDoublesGame = createSelector(

export const getIsMyGo = createSelector(getGame, game => game.isMyGo)
export const getIamGoer = createSelector(getGame, game => game.iamGoer)
export const getIHavePlayed = createSelector(getGame, game => {
if (game.iamGoer) return false

const myPosition = game.players.findIndex(p => p.id === game.me?.id)
const currentPlayerPosition = game.players.findIndex(
p => p.id === game.round?.currentHand.currentPlayerId,
)
return myPosition < currentPlayerPosition
})
export const getIamSpectator = createSelector(
getGame,
game => game.iamSpectator,
)

export const getCanBuyCards = createSelector(
getIsMyGo,
getIamGoer,
export const haveBoughtCards = createSelector(
getIsRoundBuying,
(isMyGo, iamGoer, isRoundBuying) => isMyGo && iamGoer && isRoundBuying,
isRoundBuying => isRoundBuying,
)

export const getIsInBunker = createSelector(
Expand Down
6 changes: 6 additions & 0 deletions src/caches/MyCardsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ export const myCardsSlice = createSlice({
if (c.name === action.payload.name) c.selected = !c.selected
else c.selected = false
}),
selectAll: state => {
state.cards.forEach(c => {
if (c.name !== BLANK_CARD.name) c.selected = true
})
},
clearSelectedCards: state => {
state.cards.forEach(c => {
c.selected = false
Expand All @@ -55,6 +60,7 @@ export const {
replaceMyCards,
removeCard,
clearSelectedCards,
selectAll,
toggleSelect,
toggleUniqueSelect,
clearMyCards,
Expand Down
10 changes: 0 additions & 10 deletions src/components/Game/AutoActionManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import GameService from "../../services/GameService"

import { useAppDispatch, useAppSelector } from "../../caches/hooks"
import {
getCanBuyCards,
getCards,
getGameId,
getIsInBunker,
Expand All @@ -26,7 +25,6 @@ const AutoActionManager = () => {

const autoPlayCard = useAppSelector(getAutoPlayCard)

const canBuyCards = useAppSelector(getCanBuyCards)
const isMyGo = useAppSelector(getIsMyGo)
const isInBunker = useAppSelector(getIsInBunker)

Expand All @@ -40,9 +38,6 @@ const AutoActionManager = () => {
const call = (id: string, callAmount: number) =>
dispatch(GameService.call(id, callAmount)).catch(console.error)

const buyCards = (gameId: string, cardsToBuy: string[]) =>
dispatch(GameService.buyCards(gameId, cardsToBuy)).catch(console.error)

// If in the bunker, Pass
useEffect(() => {
if (gameId && isInBunker) call(gameId, 0)
Expand All @@ -65,11 +60,6 @@ const AutoActionManager = () => {
}
}, [gameId, round, isMyGo, cards, autoPlayCard])

// Buy cards in if you are the goer
useEffect(() => {
if (gameId && canBuyCards && cards.length <= 5) buyCards(gameId, cards)
}, [gameId, cards, canBuyCards])

return null
}

Expand Down
89 changes: 52 additions & 37 deletions src/components/Game/Buying.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { Button, ButtonGroup, Form, CardBody } from "reactstrap"
import { Button, ButtonGroup, CardBody } from "reactstrap"

import { useCallback, useState } from "react"
import { useCallback, useEffect, useState } from "react"

import GameService from "../../services/GameService"
import { useAppDispatch, useAppSelector } from "../../caches/hooks"
import { useSnackbar } from "notistack"
import {
getMyCardsWithoutBlanks,
getSelectedCards,
selectAll,
} from "../../caches/MyCardsSlice"
import {
getGameId,
getIamGoer,
getIHavePlayed,
getIsMyGo,
getIsRoundBuying,
getSuit,
} from "../../caches/GameSlice"
import { riskOfMistakeBuyingCards } from "../../utils/GameUtils"
Expand All @@ -26,24 +28,18 @@ const Buying = () => {
const gameId = useAppSelector(getGameId)
const suit = useAppSelector(getSuit)
const myCards = useAppSelector(getMyCardsWithoutBlanks)
const isBuying = useAppSelector(getIsRoundBuying)
const [readyToBuy, setReadyToBuy] = useState(false)
const iHavePlayed = useAppSelector(getIHavePlayed)
const isMyGo = useAppSelector(getIsMyGo)
const iamGoer = useAppSelector(getIamGoer)

const [deleteCardsDialog, updateDeleteCardsDialog] = useState(false)

const selectedCards = useAppSelector(getSelectedCards)

const buyCardsFormSubmit = useCallback(
(e?: React.FormEvent) => {
if (e) e.preventDefault()
if (!gameId) throw Error("No game id set")

if (riskOfMistakeBuyingCards(suit!, selectedCards, myCards))
showCancelDeleteCardsDialog()
else buyCards(gameId, selectedCards)
},
[gameId, suit, selectedCards, myCards],
)
const toggleReadyToBuy = useCallback(() => {
setReadyToBuy(!readyToBuy)
}, [readyToBuy])

const buyCards = (id: string, sel: SelectableCard[]) => {
dispatch(GameService.buyCards(id, sel)).catch(e =>
Expand All @@ -55,32 +51,51 @@ const Buying = () => {
updateDeleteCardsDialog(false)
}, [])

const showCancelDeleteCardsDialog = () => {
updateDeleteCardsDialog(true)
}
useEffect(() => {
if (iamGoer) {
dispatch(selectAll())
setReadyToBuy(true)
}
}, [iamGoer])

useEffect(() => {
if (isMyGo && readyToBuy) {
if (!gameId) throw Error("No game id set")

if (riskOfMistakeBuyingCards(suit!, selectedCards, myCards)) {
setReadyToBuy(false)
updateDeleteCardsDialog(true)
} else buyCards(gameId, selectedCards)
}
}, [gameId, suit, selectedCards, myCards, isMyGo, readyToBuy])

return (
<div>
{isBuying ? (
<CardBody className="buttonArea">
<Form onSubmit={buyCardsFormSubmit}>
<ButtonGroup size="lg">
{isMyGo ? (
<Button type="submit" color="warning">
<b>Keep Cards</b>
</Button>
) : null}
</ButtonGroup>
</Form>
<CardBody className="buttonArea">
<ButtonGroup size="lg">
{!iHavePlayed ? (
<Button
type="button"
onClick={toggleReadyToBuy}
color={
isMyGo || !readyToBuy ? "warning" : "secondary"
}>
<b>
{isMyGo || !readyToBuy
? "Keep Cards"
: "Waiting to buy cards (click to cancel)"}
</b>
</Button>
) : null}
</ButtonGroup>

<ThrowCardsWarningModal
modalVisible={deleteCardsDialog}
cancelCallback={hideCancelDeleteCardsDialog}
continueCallback={buyCards}
suit={suit!}
/>
</CardBody>
) : null}
<ThrowCardsWarningModal
modalVisible={deleteCardsDialog}
cancelCallback={hideCancelDeleteCardsDialog}
continueCallback={buyCards}
suit={suit!}
/>
</CardBody>
</div>
)
}
Expand Down
105 changes: 51 additions & 54 deletions src/components/Game/Calling.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Button, ButtonGroup, CardBody } from "reactstrap"
import GameService from "../../services/GameService"
import { useAppDispatch, useAppSelector } from "../../caches/hooks"
import { getGame, getGameId } from "../../caches/GameSlice"
import { RoundStatus } from "../../model/Round"
import { useCallback } from "react"
import { useSnackbar } from "notistack"
import parseError from "../../utils/ErrorUtils"
Expand Down Expand Up @@ -36,67 +35,65 @@ const Calling = () => {
}
return (
<div>
{!!game.round && game.round.status === RoundStatus.CALLING ? (
<CardBody className="buttonArea">
<ButtonGroup size="lg">
<CardBody className="buttonArea">
<ButtonGroup size="lg">
<Button
disabled={!buttonsEnabled}
type="button"
color="secondary"
onClick={() => call(0)}>
Pass
</Button>
{game.players.length === 6 &&
((game.iamDealer && game.maxCall! <= 10) ||
game.maxCall! < 10) ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="secondary"
onClick={() => call(0)}>
Pass
color="primary"
onClick={() => call(10)}>
10
</Button>
{game.players.length === 6 &&
((game.iamDealer && game.maxCall! <= 10) ||
game.maxCall! < 10) ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="primary"
onClick={() => call(10)}>
10
</Button>
) : null}
{(game.iamDealer && game.maxCall! <= 15) ||
game.maxCall! < 15 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="warning"
onClick={() => call(15)}>
15
</Button>
) : null}
{(game.iamDealer && game.maxCall! <= 20) ||
game.maxCall! < 20 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="warning"
onClick={() => call(20)}>
20
</Button>
) : null}
{(game.iamDealer && game.maxCall! <= 25) ||
game.maxCall! < 25 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="warning"
onClick={() => call(25)}>
25
</Button>
) : null}
) : null}
{(game.iamDealer && game.maxCall! <= 15) ||
game.maxCall! < 15 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="danger"
onClick={() => call(30)}>
{game.players.length > 2 ? "Jink" : "30"}
color="warning"
onClick={() => call(15)}>
15
</Button>
</ButtonGroup>
</CardBody>
) : null}
) : null}
{(game.iamDealer && game.maxCall! <= 20) ||
game.maxCall! < 20 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="warning"
onClick={() => call(20)}>
20
</Button>
) : null}
{(game.iamDealer && game.maxCall! <= 25) ||
game.maxCall! < 25 ? (
<Button
disabled={!buttonsEnabled}
type="button"
color="warning"
onClick={() => call(25)}>
25
</Button>
) : null}
<Button
disabled={!buttonsEnabled}
type="button"
color="danger"
onClick={() => call(30)}>
{game.players.length > 2 ? "Jink" : "30"}
</Button>
</ButtonGroup>
</CardBody>
</div>
)
}
Expand Down
12 changes: 9 additions & 3 deletions src/components/Game/GameWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ import SelectSuit from "./SelectSuit"
import WebsocketManager from "./WebsocketManager"

import { useAppSelector } from "../../caches/hooks"
import { getIamSpectator } from "../../caches/GameSlice"
import {
getIamSpectator,
getIsRoundBuying,
getIsRoundCalling,
} from "../../caches/GameSlice"

const GameWrapper = () => {
const iamSpectator = useAppSelector(getIamSpectator)
const isBuying = useAppSelector(getIsRoundBuying)
const isCalling = useAppSelector(getIsRoundCalling)

return (
<CardGroup>
Expand All @@ -21,8 +27,8 @@ const GameWrapper = () => {
<PlayersAndCards />

{!iamSpectator ? <MyCards /> : null}
{!iamSpectator ? <Calling /> : null}
{!iamSpectator ? <Buying /> : null}
{!iamSpectator && isCalling ? <Calling /> : null}
{!iamSpectator && isBuying ? <Buying /> : null}
{!iamSpectator ? <SelectSuit /> : null}
</Card>
</CardGroup>
Expand Down

0 comments on commit cb00d0a

Please sign in to comment.