Skip to content

Commit b13bd68

Browse files
authored
Merge pull request #22 from devklick/feature/18_HighlightWinner
Feature/18 highlight winner
2 parents 45be15c + 3ac1c4d commit b13bd68

File tree

7 files changed

+95
-28
lines changed

7 files changed

+95
-28
lines changed

src/components/Card/Card.module.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@
2020
justify-content: center;
2121
container-type: inline-size;
2222
}
23+
24+
.CardHighlight {
25+
-webkit-animation: glow 1s ease-in-out infinite alternate;
26+
-moz-animation: glow 1s ease-in-out infinite alternate;
27+
animation: glow 1s ease-in-out infinite alternate;
28+
}
29+
30+
.CardDim {
31+
opacity: 0.7;
32+
}
33+
2334
.CardContent {
2435
text-align: center;
2536
overflow-wrap: break-word;
@@ -40,3 +51,14 @@
4051
transform: translateX(0);
4152
}
4253
}
54+
55+
@keyframes glow {
56+
from {
57+
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,
58+
0 0 14px #84b893;
59+
}
60+
to {
61+
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,
62+
0 0 14px #1e5e31;
63+
}
64+
}

src/components/Card/Card.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ import {
66

77
import styles from "./Card.module.scss";
88

9-
export interface CardProps extends CardObject {}
9+
export type CardEffect = "highlight" | "dim" | "none";
10+
export interface CardProps extends CardObject {
11+
effect: CardEffect;
12+
}
1013

11-
function Card({ rank, suit, facing }: CardProps) {
14+
function Card({ rank, suit, facing, effect }: CardProps) {
1215
const suitData = CardSuitMetadataMap[suit];
1316
const rankData = CardRankMetadataMap[rank];
1417

@@ -20,9 +23,15 @@ function Card({ rank, suit, facing }: CardProps) {
2023
content = ["?"];
2124
}
2225

26+
const cardClasses = [
27+
styles.Card,
28+
effect === "dim" && styles.CardDim,
29+
effect === "highlight" && styles.CardHighlight,
30+
].join(" ");
31+
2332
return (
2433
<div className={styles.CardWrapper}>
25-
<div className={styles.Card} style={{ backgroundColor: color }}>
34+
<div className={cardClasses} style={{ backgroundColor: color }}>
2635
<div className={styles.CardContent}>{content}</div>
2736
</div>
2837
</div>

src/components/CardRow/CardRow.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,35 @@ import { CardObject } from "../Card";
44

55
import styles from "./CardRow.module.scss";
66
import React from "react";
7+
import { CardEffect } from "../Card/Card";
78

89
export interface CardRowProps {
910
cardOwner: Participant;
1011
cards: CardObject[];
12+
effect: CardEffect;
1113
children?: React.ReactNode;
1214
}
1315

14-
const CardRow = (props: CardRowProps) => {
16+
const CardRow = ({ cardOwner, cards, effect, children }: CardRowProps) => {
1517
return (
1618
<div className={styles.CardRow}>
1719
<div className={styles.CardOwner}>
18-
<span>{props.cardOwner} Cards</span>
20+
<span>{cardOwner} Cards</span>
1921
{/*
2022
Pretty hacky, but the settings icon is passed
2123
into this row as a child element
2224
*/}
23-
{props.children}
25+
{children}
2426
</div>
2527
<div className={styles.Cards}>
26-
{props.cards.map(({ facing, rank, suit }, i) => (
27-
<Card facing={facing} rank={rank} suit={suit} key={i}></Card>
28+
{cards.map(({ facing, rank, suit }, i) => (
29+
<Card
30+
facing={facing}
31+
rank={rank}
32+
suit={suit}
33+
key={i}
34+
effect={effect}
35+
/>
2836
))}
2937
</div>
3038
</div>

src/components/Table/Table.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { useState } from "react";
22
import CardRow from "../CardRow";
33
import InfoHud from "../InfoHud";
44
import YesNoPopUp from "../YesNoPopUp";
5-
import { useGame } from ".";
5+
import { Participant, useGame } from ".";
66
import { ScoreBoardRow } from "../ScoreBoard";
77
import { useGameSettingsStore } from "../../stores/gameSettingsStore";
88

99
import styles from "./Table.module.scss";
1010
import SettingsButton from "../SettingsButton";
11+
import { CardEffect } from "../Card/Card";
1112

1213
const Table = ({ hide = false }: { hide?: boolean }) => {
1314
const game = useGame();
@@ -93,14 +94,27 @@ const Table = ({ hide = false }: { hide?: boolean }) => {
9394
];
9495
}
9596

97+
function getCardEffect(cardOwner: Participant): CardEffect {
98+
if (game.winner === "none") return "none";
99+
return cardOwner === game.winner ? "highlight" : "dim";
100+
}
101+
96102
return (
97103
<div className={styles.Table} style={{ display: hide ? "none" : "" }}>
98104
{showHitWarning && getHitWarning()}
99105
{showStickWarning && getStickWarning()}
100-
<CardRow cardOwner={"Dealer"} cards={game.dealer.cards}>
106+
<CardRow
107+
cardOwner={"Dealer"}
108+
cards={game.dealer.cards}
109+
effect={getCardEffect("Dealer")}
110+
>
101111
<SettingsButton />
102112
</CardRow>
103-
<CardRow cardOwner={"Player"} cards={game.player.cards} />
113+
<CardRow
114+
cardOwner={"Player"}
115+
cards={game.player.cards}
116+
effect={getCardEffect("Player")}
117+
/>
104118
<InfoHud
105119
gameState={game.state}
106120
outcome={game.outcome}

src/components/Table/hooks/useGame.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ export type GameState =
1313
| "GameOver";
1414

1515
export type Participant = "Player" | "Dealer";
16+
export type Winner = Participant | "none";
17+
export type WinType =
18+
| "opponent-bust"
19+
| "five-card-trick"
20+
| "high-score"
21+
| "most-cards"
22+
| "high-card"
23+
| "draw";
1624

1725
export function useGame() {
1826
const [state, setState] = useState<GameState>("WaitingForStart");
1927
const [outcome, setOutcome] = useState<string | null>(null);
28+
const [winner, setWinner] = useState<Winner>("none");
2029

2130
const deck = useDeck();
2231
const player = useCardPile();
@@ -68,7 +77,7 @@ export function useGame() {
6877
let timeout: NodeJS.Timeout | undefined;
6978

7079
if (dealer.bust) {
71-
setResult("Dealer bust, dealer wins!", "Player");
80+
setResult("Dealer bust, player wins!", "Player");
7281
} else if (dealer.fiveCardTrick) {
7382
setResult("Dealer wins with a five card trick!", "Dealer");
7483
}
@@ -133,6 +142,7 @@ export function useGame() {
133142
*/
134143
function setup() {
135144
setOutcome(null);
145+
setWinner("none");
136146
deck.init();
137147

138148
player.setCards([]);
@@ -196,6 +206,7 @@ export function useGame() {
196206
function setResult(outcomeText: string, winner?: Participant | null): void {
197207
setState("GameOver");
198208
setOutcome(outcomeText);
209+
setWinner(winner ?? "none");
199210

200211
winner && stats.updateWinnerStats(winner);
201212
}
@@ -223,6 +234,11 @@ export function useGame() {
223234
* Statistics about the games played during this session.
224235
*/
225236
stats,
237+
238+
/**
239+
* The participant who won the round, if any.
240+
*/
241+
winner,
226242
setup,
227243
startDealerRound,
228244
getParticipantScore,

src/utilities/deckUtilities.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe("deckUtilities", () => {
1010
cards: [
1111
{
1212
card: { facing: "Up", rank: "Ace", suit: "Club" },
13-
rankRelativeValueUsed: Math.min(
13+
rankGlobalValueUsed: Math.min(
1414
...CardRankMetadataMap["Ace"].relativeValues
1515
),
1616
rankValueUsed: Math.min(...CardRankMetadataMap["Ace"].values),
@@ -22,7 +22,7 @@ describe("deckUtilities", () => {
2222
cards: [
2323
{
2424
card: { facing: "Up", rank: "Ace", suit: "Diamond" },
25-
rankRelativeValueUsed: Math.min(
25+
rankGlobalValueUsed: Math.min(
2626
...CardRankMetadataMap["Ace"].relativeValues
2727
),
2828
rankValueUsed: Math.min(...CardRankMetadataMap["Ace"].values),
@@ -51,7 +51,7 @@ describe("deckUtilities", () => {
5151
it("Should return Dealer when dealer has more cards than player", () => {
5252
dealerHand.cards.push({
5353
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
54-
rankRelativeValueUsed: 8,
54+
rankGlobalValueUsed: 8,
5555
rankValueUsed: 8,
5656
});
5757
dealerHand.score = playerHand.score;
@@ -63,7 +63,7 @@ describe("deckUtilities", () => {
6363
it("Should return Player when player has more cards than player", () => {
6464
playerHand.cards.push({
6565
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
66-
rankRelativeValueUsed: 8,
66+
rankGlobalValueUsed: 8,
6767
rankValueUsed: 8,
6868
});
6969
playerHand.score = dealerHand.score;
@@ -77,12 +77,12 @@ describe("deckUtilities", () => {
7777
it("Should return Dealer when dealers high card is greater than players", () => {
7878
dealerHand.cards.push({
7979
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
80-
rankRelativeValueUsed: 8,
80+
rankGlobalValueUsed: 8,
8181
rankValueUsed: 8,
8282
});
8383
playerHand.cards.push({
8484
card: { facing: "Up", rank: "Seven", suit: "Diamond" },
85-
rankRelativeValueUsed: 7,
85+
rankGlobalValueUsed: 7,
8686
rankValueUsed: 7,
8787
});
8888
dealerHand.score = playerHand.score;
@@ -94,12 +94,12 @@ describe("deckUtilities", () => {
9494
it("Should return Player when player has more cards than player", () => {
9595
dealerHand.cards.push({
9696
card: { facing: "Up", rank: "Seven", suit: "Diamond" },
97-
rankRelativeValueUsed: 7,
97+
rankGlobalValueUsed: 7,
9898
rankValueUsed: 7,
9999
});
100100
playerHand.cards.push({
101101
card: { facing: "Up", rank: "Eight", suit: "Diamond" },
102-
rankRelativeValueUsed: 8,
102+
rankGlobalValueUsed: 8,
103103
rankValueUsed: 8,
104104
});
105105
playerHand.score = dealerHand.score;

src/utilities/deckUtilities.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export const generateDeck = (
100100
export interface CardValue {
101101
card: CardObject;
102102
rankValueUsed: number;
103-
rankRelativeValueUsed: number;
103+
rankGlobalValueUsed: number;
104104
}
105105
export interface BestHand {
106106
score: number;
@@ -125,12 +125,12 @@ export const calculateBestHand = (cards: CardObject[]): BestHand => {
125125
}
126126

127127
const cardValue = Math.max(...CardRankMetadataMap[card.rank].values);
128-
const cardRelativeValue = Math.max(
128+
const cardGlobalValue = Math.max(
129129
...CardRankMetadataMap[card.rank].relativeValues
130130
);
131131
bestHand.cards.push({
132132
card,
133-
rankRelativeValueUsed: cardRelativeValue,
133+
rankGlobalValueUsed: cardGlobalValue,
134134
rankValueUsed: cardValue,
135135
});
136136
bestHand.score += cardValue;
@@ -197,17 +197,15 @@ export const determineWinner = (
197197
};
198198

199199
const getHighestCardValue = (cards: CardValue[]) => {
200-
return cards.sort((a, b) => b.rankValueUsed - a.rankValueUsed)[0];
200+
return cards.sort((a, b) => b.rankGlobalValueUsed - a.rankGlobalValueUsed)[0];
201201
};
202202

203203
const getHighCardWinner = (
204204
playerCards: CardValue[],
205205
dealerCards: CardValue[]
206206
): GameResult | null => {
207-
const playerHighCard = getHighestCardValue(playerCards).rankValueUsed;
208-
console.log("playerHighCard", playerHighCard);
209-
const dealerHighCard = getHighestCardValue(dealerCards).rankValueUsed;
210-
console.log("dealerHighCard", dealerHighCard);
207+
const playerHighCard = getHighestCardValue(playerCards).rankGlobalValueUsed;
208+
const dealerHighCard = getHighestCardValue(dealerCards).rankGlobalValueUsed;
211209

212210
const winner = getPlayerWithHighestValue(playerHighCard, dealerHighCard);
213211
if (!winner) return null;

0 commit comments

Comments
 (0)