redraw cards

This commit is contained in:
Gavin McDonald
2025-06-12 11:53:35 -04:00
parent 5c18b8afbf
commit e75d9b41bc
6 changed files with 79 additions and 9 deletions

View File

@@ -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])}
/>
)}
</div>

View File

@@ -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<React.ReactNode>(null);
const { aria, flipped } = card;
@@ -71,8 +79,8 @@ export default function Card({ dm, card, position, settings, flipAction }: CardP
/>
{dm && !flipped && (
<StackTheDeck
onRedo={() => console.log('Redo')}
onPick={() => console.log('Pick')}
onRedraw={redrawAction}
onSelect={() => console.log('Pick')}
onHover={setTooltip}
/>
)}

View File

@@ -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(<p className="text-yellow-400">Redraw</p>)}
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)}
>
<RefreshCw className="w-3 h-3" />
</button>
@@ -39,7 +39,7 @@ export default function StackTheDeck({
onTouchStart={() => onHover(<p className="text-yellow-400">Select</p>)}
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)}
>
<GalleryHorizontalEnd className="w-3 h-3" />
</button>

View File

@@ -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);

View File

@@ -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];
}

View File

@@ -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);