diff --git a/src/components/Card/Card.module.scss b/src/components/Card/Card.module.scss
index a289ac6..16f67af 100644
--- a/src/components/Card/Card.module.scss
+++ b/src/components/Card/Card.module.scss
@@ -20,6 +20,17 @@
justify-content: center;
container-type: inline-size;
}
+
+.CardHighlight {
+ -webkit-animation: glow 1s ease-in-out infinite alternate;
+ -moz-animation: glow 1s ease-in-out infinite alternate;
+ animation: glow 1s ease-in-out infinite alternate;
+}
+
+.CardDim {
+ opacity: 0.7;
+}
+
.CardContent {
text-align: center;
overflow-wrap: break-word;
@@ -40,3 +51,14 @@
transform: translateX(0);
}
}
+
+@keyframes glow {
+ from {
+ box-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #84b893, 0 0 8px #84b893, 0 0 10px #84b893, 0 0 12px #84b893,
+ 0 0 14px #84b893;
+ }
+ to {
+ box-shadow: 0 0 2px #fff, 0 0 4px #fff, 0 0 6px #1e5e31, 0 0 8px #1e5e31, 0 0 10px #1e5e31, 0 0 12px #1e5e31,
+ 0 0 14px #1e5e31;
+ }
+}
diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx
index a722912..38645f8 100644
--- a/src/components/Card/Card.tsx
+++ b/src/components/Card/Card.tsx
@@ -6,9 +6,12 @@ import {
import styles from "./Card.module.scss";
-export interface CardProps extends CardObject {}
+export type CardEffect = "highlight" | "dim" | "none";
+export interface CardProps extends CardObject {
+ effect: CardEffect;
+}
-function Card({ rank, suit, facing }: CardProps) {
+function Card({ rank, suit, facing, effect }: CardProps) {
const suitData = CardSuitMetadataMap[suit];
const rankData = CardRankMetadataMap[rank];
@@ -20,9 +23,15 @@ function Card({ rank, suit, facing }: CardProps) {
content = ["?"];
}
+ const cardClasses = [
+ styles.Card,
+ effect === "dim" && styles.CardDim,
+ effect === "highlight" && styles.CardHighlight,
+ ].join(" ");
+
return (
-
diff --git a/src/components/CardRow/CardRow.tsx b/src/components/CardRow/CardRow.tsx
index 135d78d..29df9ce 100644
--- a/src/components/CardRow/CardRow.tsx
+++ b/src/components/CardRow/CardRow.tsx
@@ -4,27 +4,35 @@ import { CardObject } from "../Card";
import styles from "./CardRow.module.scss";
import React from "react";
+import { CardEffect } from "../Card/Card";
export interface CardRowProps {
cardOwner: Participant;
cards: CardObject[];
+ effect: CardEffect;
children?: React.ReactNode;
}
-const CardRow = (props: CardRowProps) => {
+const CardRow = ({ cardOwner, cards, effect, children }: CardRowProps) => {
return (
- {props.cardOwner} Cards
+ {cardOwner} Cards
{/*
Pretty hacky, but the settings icon is passed
into this row as a child element
*/}
- {props.children}
+ {children}
- {props.cards.map(({ facing, rank, suit }, i) => (
-
+ {cards.map(({ facing, rank, suit }, i) => (
+
))}
diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx
index c163cca..9c3e6f4 100644
--- a/src/components/Table/Table.tsx
+++ b/src/components/Table/Table.tsx
@@ -2,12 +2,13 @@ import { useState } from "react";
import CardRow from "../CardRow";
import InfoHud from "../InfoHud";
import YesNoPopUp from "../YesNoPopUp";
-import { useGame } from ".";
+import { Participant, useGame } from ".";
import { ScoreBoardRow } from "../ScoreBoard";
import { useGameSettingsStore } from "../../stores/gameSettingsStore";
import styles from "./Table.module.scss";
import SettingsButton from "../SettingsButton";
+import { CardEffect } from "../Card/Card";
const Table = ({ hide = false }: { hide?: boolean }) => {
const game = useGame();
@@ -93,14 +94,27 @@ const Table = ({ hide = false }: { hide?: boolean }) => {
];
}
+ function getCardEffect(cardOwner: Participant): CardEffect {
+ if (game.winner === "none") return "none";
+ return cardOwner === game.winner ? "highlight" : "dim";
+ }
+
return (
{showHitWarning && getHitWarning()}
{showStickWarning && getStickWarning()}
-
+
-
+
("WaitingForStart");
const [outcome, setOutcome] = useState(null);
+ const [winner, setWinner] = useState("none");
const deck = useDeck();
const player = useCardPile();
@@ -68,7 +77,7 @@ export function useGame() {
let timeout: NodeJS.Timeout | undefined;
if (dealer.bust) {
- setResult("Dealer bust, dealer wins!", "Player");
+ setResult("Dealer bust, player wins!", "Player");
} else if (dealer.fiveCardTrick) {
setResult("Dealer wins with a five card trick!", "Dealer");
}
@@ -133,6 +142,7 @@ export function useGame() {
*/
function setup() {
setOutcome(null);
+ setWinner("none");
deck.init();
player.setCards([]);
@@ -196,6 +206,7 @@ export function useGame() {
function setResult(outcomeText: string, winner?: Participant | null): void {
setState("GameOver");
setOutcome(outcomeText);
+ setWinner(winner ?? "none");
winner && stats.updateWinnerStats(winner);
}
@@ -223,6 +234,11 @@ export function useGame() {
* Statistics about the games played during this session.
*/
stats,
+
+ /**
+ * The participant who won the round, if any.
+ */
+ winner,
setup,
startDealerRound,
getParticipantScore,
diff --git a/src/utilities/deckUtilities.test.ts b/src/utilities/deckUtilities.test.ts
index a4205f0..69df4af 100644
--- a/src/utilities/deckUtilities.test.ts
+++ b/src/utilities/deckUtilities.test.ts
@@ -10,7 +10,7 @@ describe("deckUtilities", () => {
cards: [
{
card: { facing: "Up", rank: "Ace", suit: "Club" },
- rankRelativeValueUsed: Math.min(
+ rankGlobalValueUsed: Math.min(
...CardRankMetadataMap["Ace"].relativeValues
),
rankValueUsed: Math.min(...CardRankMetadataMap["Ace"].values),
@@ -22,7 +22,7 @@ describe("deckUtilities", () => {
cards: [
{
card: { facing: "Up", rank: "Ace", suit: "Diamond" },
- rankRelativeValueUsed: Math.min(
+ rankGlobalValueUsed: Math.min(
...CardRankMetadataMap["Ace"].relativeValues
),
rankValueUsed: Math.min(...CardRankMetadataMap["Ace"].values),
@@ -51,7 +51,7 @@ describe("deckUtilities", () => {
it("Should return Dealer when dealer has more cards than player", () => {
dealerHand.cards.push({
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
- rankRelativeValueUsed: 8,
+ rankGlobalValueUsed: 8,
rankValueUsed: 8,
});
dealerHand.score = playerHand.score;
@@ -63,7 +63,7 @@ describe("deckUtilities", () => {
it("Should return Player when player has more cards than player", () => {
playerHand.cards.push({
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
- rankRelativeValueUsed: 8,
+ rankGlobalValueUsed: 8,
rankValueUsed: 8,
});
playerHand.score = dealerHand.score;
@@ -77,12 +77,12 @@ describe("deckUtilities", () => {
it("Should return Dealer when dealers high card is greater than players", () => {
dealerHand.cards.push({
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
- rankRelativeValueUsed: 8,
+ rankGlobalValueUsed: 8,
rankValueUsed: 8,
});
playerHand.cards.push({
card: { facing: "Up", rank: "Seven", suit: "Diamond" },
- rankRelativeValueUsed: 7,
+ rankGlobalValueUsed: 7,
rankValueUsed: 7,
});
dealerHand.score = playerHand.score;
@@ -94,12 +94,12 @@ describe("deckUtilities", () => {
it("Should return Player when player has more cards than player", () => {
dealerHand.cards.push({
card: { facing: "Up", rank: "Seven", suit: "Diamond" },
- rankRelativeValueUsed: 7,
+ rankGlobalValueUsed: 7,
rankValueUsed: 7,
});
playerHand.cards.push({
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
- rankRelativeValueUsed: 8,
+ rankGlobalValueUsed: 8,
rankValueUsed: 8,
});
playerHand.score = dealerHand.score;
diff --git a/src/utilities/deckUtilities.ts b/src/utilities/deckUtilities.ts
index 18a2f71..1fc85f6 100644
--- a/src/utilities/deckUtilities.ts
+++ b/src/utilities/deckUtilities.ts
@@ -100,7 +100,7 @@ export const generateDeck = (
export interface CardValue {
card: CardObject;
rankValueUsed: number;
- rankRelativeValueUsed: number;
+ rankGlobalValueUsed: number;
}
export interface BestHand {
score: number;
@@ -125,12 +125,12 @@ export const calculateBestHand = (cards: CardObject[]): BestHand => {
}
const cardValue = Math.max(...CardRankMetadataMap[card.rank].values);
- const cardRelativeValue = Math.max(
+ const cardGlobalValue = Math.max(
...CardRankMetadataMap[card.rank].relativeValues
);
bestHand.cards.push({
card,
- rankRelativeValueUsed: cardRelativeValue,
+ rankGlobalValueUsed: cardGlobalValue,
rankValueUsed: cardValue,
});
bestHand.score += cardValue;
@@ -197,17 +197,15 @@ export const determineWinner = (
};
const getHighestCardValue = (cards: CardValue[]) => {
- return cards.sort((a, b) => b.rankValueUsed - a.rankValueUsed)[0];
+ return cards.sort((a, b) => b.rankGlobalValueUsed - a.rankGlobalValueUsed)[0];
};
const getHighCardWinner = (
playerCards: CardValue[],
dealerCards: CardValue[]
): GameResult | null => {
- const playerHighCard = getHighestCardValue(playerCards).rankValueUsed;
- console.log("playerHighCard", playerHighCard);
- const dealerHighCard = getHighestCardValue(dealerCards).rankValueUsed;
- console.log("dealerHighCard", dealerHighCard);
+ const playerHighCard = getHighestCardValue(playerCards).rankGlobalValueUsed;
+ const dealerHighCard = getHighestCardValue(dealerCards).rankGlobalValueUsed;
const winner = getPlayerWithHighestValue(playerHighCard, dealerHighCard);
if (!winner) return null;