From e75d9b41bcedaeb4202044df48c1db0395110c14 Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Thu, 12 Jun 2025 11:53:35 -0400 Subject: [PATCH] redraw cards --- app/[gameID]/page.tsx | 10 ++++++++++ components/Card.tsx | 14 +++++++++++--- components/StackTheDeck.tsx | 12 ++++++------ lib/GameStore.ts | 13 +++++++++++++ lib/TarokkaDeck.ts | 24 ++++++++++++++++++++++++ server.ts | 15 +++++++++++++++ 6 files changed, 79 insertions(+), 9 deletions(-) diff --git a/app/[gameID]/page.tsx b/app/[gameID]/page.tsx index 4710db2..184f1ce 100644 --- a/app/[gameID]/page.tsx +++ b/app/[gameID]/page.tsx @@ -78,6 +78,15 @@ export default function GamePage() { socket.emit('flip-card', flip); }; + const redraw = (cardIndex: number) => { + const redraw: ClientUpdate = { + gameID, + cardIndex, + }; + + socket.emit('redraw', redraw); + }; + const handleSettings = (gameData: GameUpdate) => { socket.emit('settings', { gameID, gameData }); }; @@ -114,6 +123,7 @@ export default function GamePage() { position={layout[cardMap[index]]} settings={settings} flipAction={() => flipCard(cardMap[index])} + redrawAction={() => redraw(cardMap[index])} /> )} diff --git a/components/Card.tsx b/components/Card.tsx index a54aa92..3cabc45 100644 --- a/components/Card.tsx +++ b/components/Card.tsx @@ -17,9 +17,17 @@ type CardProps = { position: Layout; settings: Settings; flipAction: () => void; + redrawAction: () => void; }; -export default function Card({ dm, card, position, settings, flipAction }: CardProps) { +export default function Card({ + dm, + card, + position, + settings, + flipAction, + redrawAction, +}: CardProps) { const [tooltip, setTooltip] = useState(null); const { aria, flipped } = card; @@ -71,8 +79,8 @@ export default function Card({ dm, card, position, settings, flipAction }: CardP /> {dm && !flipped && ( console.log('Redo')} - onPick={() => console.log('Pick')} + onRedraw={redrawAction} + onSelect={() => console.log('Pick')} onHover={setTooltip} /> )} diff --git a/components/StackTheDeck.tsx b/components/StackTheDeck.tsx index 305dc1b..35a7773 100644 --- a/components/StackTheDeck.tsx +++ b/components/StackTheDeck.tsx @@ -1,15 +1,15 @@ import { GalleryHorizontalEnd, RefreshCw } from 'lucide-react'; interface StackTheDeckProps { - onRedo: () => void; - onPick: () => void; + onRedraw: () => void; + onSelect: () => void; onHover: (state: React.ReactNode) => void; className?: string; } export default function StackTheDeck({ - onRedo, - onPick, + onRedraw, + onSelect, onHover, className = '', }: StackTheDeckProps) { @@ -28,7 +28,7 @@ export default function StackTheDeck({ onTouchStart={() => onHover(

Redraw

)} onTouchEnd={() => onHover(null)} className={`p-1 transition-all duration-250 text-yellow-400 hover:text-yellow-300 hover:drop-shadow-[0_0_3px_#ffd700] cursor-pointer`} - onClick={curryHandleClick(onRedo)} + onClick={curryHandleClick(onRedraw)} > @@ -39,7 +39,7 @@ export default function StackTheDeck({ onTouchStart={() => onHover(

Select

)} onTouchEnd={() => onHover(null)} className={`p-1 transition-all duration-250 text-yellow-400 hover:text-yellow-300 hover:drop-shadow-[0_0_3px_#ffd700] cursor-pointer`} - onClick={curryHandleClick(onPick)} + onClick={curryHandleClick(onSelect)} > diff --git a/lib/GameStore.ts b/lib/GameStore.ts index 635020e..b9f12e4 100644 --- a/lib/GameStore.ts +++ b/lib/GameStore.ts @@ -130,6 +130,19 @@ export default class GameStore { return this.gameUpdate(game); } + redraw(gameID: string, cardIndex: number): GameUpdate { + const game = this.getGame(gameID); + const card = game.cards[cardIndex]; + + if (!card) throw new Error(`Card ${cardIndex} not found`); + + game.cards[cardIndex] = + card.suit === 'High Deck' ? deck.drawHigh(game.cards) : deck.drawLow(game.cards); + game.lastUpdated = Date.now(); + + return this.gameUpdate(game); + } + updateSettings(gameID: string, settings: Settings) { const game = this.getGame(gameID); diff --git a/lib/TarokkaDeck.ts b/lib/TarokkaDeck.ts index e45851e..aef5d56 100644 --- a/lib/TarokkaDeck.ts +++ b/lib/TarokkaDeck.ts @@ -19,6 +19,30 @@ export default class TarokkaDeck { ); } + drawLow(exclude: TarokkaGameCard[] = []): TarokkaGameCard { + const excludeIDs = exclude.map(({ id }) => id); + + return { + ...getRandomItems( + this.commonDeck.filter(({ id }) => !excludeIDs.includes(id)), + 1, + )[0], + flipped: false, + }; + } + + drawHigh(exclude: TarokkaGameCard[] = []): TarokkaGameCard { + const excludeIDs = exclude.map(({ id }) => id); + + return { + ...getRandomItems( + this.highDeck.filter(({ id }) => !excludeIDs.includes(id)), + 1, + )[0], + flipped: false, + }; + } + getBack(): TarokkaCard { return this.backs[0]; } diff --git a/server.ts b/server.ts index 904b65d..2ce19b3 100644 --- a/server.ts +++ b/server.ts @@ -79,6 +79,21 @@ app.prepare().then(() => { } }); + socket.on('redraw', ({ gameID, cardIndex }: ClientUpdate) => { + try { + //console.log(Date.now(), 'Redraw', { gameID, cardIndex }); + + const gameUpdate = gameStore.redraw(gameID, cardIndex); + + broadcast('game-update', gameUpdate); + } catch (e) { + const error = e instanceof Error ? e.message : e; + + console.error(Date.now(), 'Error[redraw]', error); + socket.emit('redraw-error', error); + } + }); + socket.on('settings', ({ gameID, gameData }: { gameID: string; gameData: GameUpdate }) => { try { const gameUpdate = gameStore.updateSettings(gameID, gameData.settings);