Skip to content

Commit

Permalink
merge with main
Browse files Browse the repository at this point in the history
  • Loading branch information
mattgrunwald committed Nov 7, 2024
2 parents 23a448d + 03aea81 commit ddc98d1
Show file tree
Hide file tree
Showing 21 changed files with 187 additions and 92 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/sign-content/moo-deng.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/sign-content/scabby.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/sign-content/tick-tock-avatar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/sign-content/union-fist.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 0 additions & 37 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,3 @@ div#game {
aspect-ratio: 1 / 1;
padding: 0.5rem;
}

.scoreboard-container {
display: flex;
justify-content: center;
width: 100%;
padding-top: 0.5rem;
}

.scoreboard {
display: block;
padding: 0 0.5rem;
width: var(--scoreboard-width);
}

.scoreboard .row {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
}

.scoreboard p {
margin: 0;
}

.summary h1 {
margin-top: 0;
margin-bottom: 1rem;
}

.summary p {
margin-bottom: 0.5rem;
}

.summary button {
margin-top: 1rem;
}
46 changes: 18 additions & 28 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { useContext, useEffect, useState } from 'react';
import './App.css';
import { GameSettings } from './components/GameSettings';
import { Header } from './components/Header';
import { InfoDialog } from './components/InfoDialog';
import { PicketSign } from './components/PicketSign';
import { ResultsDialog } from './components/ResultsDialog';
import { Scoreboard } from './components/Scoreboard';
import { GameContext } from './contexts/gameContext';

function App() {
const {
score,
attempts,
counts,
cards,
hasMatchAllCards,
reset,
handleClick,
duration
} = useContext(GameContext);
const [gameSettingsOpen, setGameSettingsOpen] = useState(false);
const [showDialog, setShowDialog] = useState(false);
const [infoDialogOpen, setInfoDialogOpen] = useState(false);

const { cards, hasMatchAllCards, reset, handleClick } =
useContext(GameContext);

useEffect(() => {
let timeout: number | undefined;
if (hasMatchAllCards) {
Expand All @@ -35,12 +31,20 @@ function App() {
return (
<>
<Header>
<a href="https://nytimesguild.org/tech/guild-builds/">More Games</a>

<span
className="link-alike"
onClick={() => setInfoDialogOpen(!infoDialogOpen)}
>
What’s this?
</span>
<span
className="link-alike"
onClick={() => setGameSettingsOpen(!gameSettingsOpen)}
>
Settings
</span>
</Header>

<div id="game-container">
Expand All @@ -56,36 +60,22 @@ function App() {
))}
</div>
</div>
<div className="scoreboard-container">
<div className="scoreboard">
<p className="time">
<strong>Time spent:</strong> {duration}
</p>
<div className="row">
<p className="attempts">
<strong>Picket signs flipped:</strong> {attempts}
</p>
<p className="score">
<strong>Matches:</strong> {score}
</p>
</div>
</div>
</div>
<Scoreboard />
{showDialog && (
<ResultsDialog
counts={counts}
attempts={attempts}
onClose={() => setShowDialog(false)}
onReset={() => {
setShowDialog(false);
reset();
}}
duration={duration}
/>
)}
{infoDialogOpen && (
<InfoDialog onClose={() => setInfoDialogOpen(false)} />
)}
{gameSettingsOpen && (
<GameSettings onClose={() => setGameSettingsOpen(false)} />
)}
</>
);
}
Expand Down
21 changes: 15 additions & 6 deletions src/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ enum SignContent {
MakerWeekGuild = 'maker-week-guild.webp',
UnionMadeGithub = 'union-made-github.webp',
WuerkerCartoon = 'wuerker-cartoon.webp',
ContractCrossword = 'contract-crossword.webp'
ContractCrossword = 'contract-crossword.webp',
DontPlayGames = 'dontplaygames-socialstrike.png',
MooDeng = 'moo-deng.png',
Scabby = 'scabby.jpg',
StandWithGuild = 'stand-with-guild-avatar.png',
TechSupport = 'tech-support-avatar.png',
TickTock = 'tick-tock-avatar.png',
UnionFist = 'union-fist.png',
ReadyToStrike = 'ready-to-strike_text-only-avatar.png',
}

export interface Card {
Expand All @@ -17,12 +25,13 @@ export interface Card {
count: number;
}

const CARD_VALUES = Object.values(SignContent);

export function getInitialCards(): Card[] {
export function getInitialCards(countCardsInPlay: number): Card[] {
const date = new Date().toISOString();
let cardValues = Object.values(SignContent);
shuffleArray(cardValues);
cardValues = cardValues.slice(0, countCardsInPlay);

const cards = [...CARD_VALUES, ...CARD_VALUES].map((value, index) => ({
const cards = [...cardValues, ...cardValues].map((value, index) => ({
value,
id: date + index,
isFaceUp: false,
Expand All @@ -34,7 +43,7 @@ export function getInitialCards(): Card[] {
}

// note, sort(() => 0.5 - Math.random()) and similar are biased; see <https://stackoverflow.com/a/12646864>
function shuffleArray(array: Card[]) {
function shuffleArray(array: unknown[]) {
for (let i = array.length - 1; i >= 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
Expand Down
1 change: 1 addition & 0 deletions src/components/Dialog/Dialog.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.dialog {
z-index: 100;
position: absolute;
top: 0;
left: 0;
Expand Down
7 changes: 7 additions & 0 deletions src/components/GameSettings/GameSettings.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.settings-container {
justify-content: start;
align-items: center;
display: flex;
flex-direction: column;
gap: 1rem;
}
43 changes: 43 additions & 0 deletions src/components/GameSettings/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useContext } from 'react';
import { Difficulty, GameContext } from '../../contexts/gameContext';
import { Dialog } from '../Dialog';
import './GameSettings.css';

export const GameSettings = ({ onClose }: { onClose: () => void }) => {
const { difficulty, setDifficulty } = useContext(GameContext);

const handleChangeDifficulty = (
event: React.ChangeEvent<HTMLSelectElement>
) => {
const newValue = event.target.value;
setDifficulty(newValue as Difficulty);
};

return (
<Dialog centerX centerY onClose={onClose}>
<div className="settings-container">
<label>Choose your difficulty:</label>

<select
name="difficulty"
id="difficulty"
value={difficulty}
onChange={handleChangeDifficulty}
>
<option value={Difficulty.EASY}>Easy</option>
<option value={Difficulty.MEDIUM}>Medium</option>
<option value={Difficulty.HARD}>Hard</option>
</select>

<button
className="button"
onClick={() => {
onClose();
}}
>
Let's Play!
</button>
</div>
</Dialog>
);
};
3 changes: 2 additions & 1 deletion src/components/Header/Header.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

> div.header-links {
justify-content: end;
& > * {
& > a,
& > .link-alike {
margin-left: 1rem;
}
}
Expand Down
1 change: 0 additions & 1 deletion src/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export const Header = ({ children }: PropsWithChildren) => (
<b>Match Strike</b>
</div>
<div className="header-links">
<a href="https://nytimesguild.org/tech/guild-builds/">More Games</a>
{children}
</div>
</div>
Expand Down
22 changes: 11 additions & 11 deletions src/components/ResultsDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { useCallback, useMemo } from 'react';
import { useCallback, useContext, useMemo } from 'react';
import { GameContext } from '../../contexts/gameContext';
import { Dialog } from '../Dialog';
import './ResultsDialog.css';

export const ResultsDialog = ({
onClose,
onReset,
duration,
counts,
attempts
onReset
}: {
onClose: () => void;
onReset: () => void;
duration: string;
counts: number[];
attempts: number;
}) => {
const { duration, counts, attempts } = useContext(GameContext);
const squares = useMemo(
() => counts.map((c) => (c === 1 ? '🟩' : c === 2 ? '🟨' : '🟥')),
() =>
counts.map((c) =>
c === 1 ? '🟦' : c === 2 ? '🟩' : c === 3 ? '🟨' : '🟥'
),
[counts]
);

Expand Down Expand Up @@ -50,8 +49,9 @@ export const ResultsDialog = ({
))}
</div>
<p className="square-key">
<span>🟩 = 1️</span>
<span>🟨 = 2</span>
<span>🟦 = 1</span>
<span>🟩 = 2</span>
<span>🟨 = 3</span>
<span>🟥 = 3+</span>
</p>
<button onClick={copyResults}>Copy to Clipboard</button>
Expand Down
23 changes: 23 additions & 0 deletions src/components/Scoreboard/Scoreboard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.scoreboard-container {
display: flex;
justify-content: center;
width: 100%;
padding-top: 0.5rem;
}

.scoreboard {
display: block;
padding: 0 0.5rem;
width: var(--scoreboard-width);
}

.scoreboard .row {
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
}

.scoreboard p {
margin: 0;
}
24 changes: 24 additions & 0 deletions src/components/Scoreboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useContext } from 'react';
import { GameContext } from '../../contexts/gameContext';
import './Scoreboard.css';

export const Scoreboard = () => {
const { duration, score, attempts } = useContext(GameContext);
return (
<div className="scoreboard-container">
<div className="scoreboard">
<p className="time">
<strong>Time spent:</strong> {duration}
</p>
<div className="row">
<p className="attempts">
<strong>Picket signs flipped:</strong> {score}
</p>
<p className="score">
<strong>Matches:</strong> {attempts}
</p>
</div>
</div>
</div>
);
};
Loading

0 comments on commit ddc98d1

Please sign in to comment.