From 70e7e982e98111196d151e2b99e18b57ee00d5a8 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 28 Aug 2022 14:51:04 +0100 Subject: [PATCH] games: add base /games page, and re-style floriferous page --- src/components/games/index.ts | 2 +- src/components/games/types.ts | 0 src/{ => lib}/components/Navbar.svelte | 0 src/lib/floriferous/floriferous-game.spec.ts | 32 ++++-- src/lib/floriferous/floriferous-game.ts | 40 ++++++- src/routes/+page.svelte | 2 +- src/routes/blog/+error.svelte | 2 +- src/routes/blog/+page.svelte | 2 +- src/routes/blog/[slug]/+page.svelte | 6 +- src/routes/games/+page.server.ts | 1 + src/routes/games/+page.svelte | 18 +++ src/routes/games/PreviousGameScores.svelte | 46 ++++++++ src/routes/games/floriferous/+page.svelte | 109 ++++++++++--------- src/routes/games/types.ts | 3 + src/styles/thomaswilson.css | 19 ++++ 15 files changed, 211 insertions(+), 71 deletions(-) create mode 100644 src/components/games/types.ts rename src/{ => lib}/components/Navbar.svelte (100%) create mode 100644 src/routes/games/+page.server.ts create mode 100644 src/routes/games/+page.svelte create mode 100644 src/routes/games/PreviousGameScores.svelte create mode 100644 src/routes/games/types.ts diff --git a/src/components/games/index.ts b/src/components/games/index.ts index 29173c3..2806140 100644 --- a/src/components/games/index.ts +++ b/src/components/games/index.ts @@ -1,3 +1,3 @@ import FloriferousPlayerForm from './FloriferousPlayerForm.svelte'; -export { FloriferousPlayerForm }; +export { FloriferousPlayerForm, PreviousGameScores }; diff --git a/src/components/games/types.ts b/src/components/games/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Navbar.svelte b/src/lib/components/Navbar.svelte similarity index 100% rename from src/components/Navbar.svelte rename to src/lib/components/Navbar.svelte diff --git a/src/lib/floriferous/floriferous-game.spec.ts b/src/lib/floriferous/floriferous-game.spec.ts index b98aa40..2ac6fae 100644 --- a/src/lib/floriferous/floriferous-game.spec.ts +++ b/src/lib/floriferous/floriferous-game.spec.ts @@ -1,6 +1,7 @@ -import { FloriferousGame } from './floriferous-game'; import { describe, it, expect } from 'vitest'; -import { FloriferousPlayer } from './floriferous-player'; + +import { FloriferousGame } from './floriferous-game.js'; +import { FloriferousPlayer } from './floriferous-player.js'; describe('FloriferousGame', () => { const alice = new FloriferousPlayer({ @@ -15,6 +16,12 @@ describe('FloriferousGame', () => { rowAtEndOfGame: 1 }); + const bobWithTwoPoints = new FloriferousPlayer({ + name: 'Bob', + score: 2, + rowAtEndOfGame: 1 + }); + it('Determines a winner', () => { const game = new FloriferousGame(); @@ -28,11 +35,6 @@ describe('FloriferousGame', () => { it('Breaks a tie using the player closest to the top of the board', () => { // GIVEN - const bobWithTwoPoints = new FloriferousPlayer({ - name: 'Bob', - score: 2, - rowAtEndOfGame: 1 - }); const game = new FloriferousGame(); @@ -43,4 +45,20 @@ describe('FloriferousGame', () => { // THEN expect(game.winner).toBe('Alice'); }); + + it('Can give a pretty summary', () => { + // GIVEN + const game = new FloriferousGame({ + playedTs: new Date('2022-08-28T13:12Z'), + players: [alice, bob] + }); + + // WHEN + const prettySummary = game.prettySummary; + + // THEN + expect(prettySummary).toBe( + 'Sunday, 28 August 2022, 14:12: Alice won with 2 points. Bob: 1 point.' + ); + }); }); diff --git a/src/lib/floriferous/floriferous-game.ts b/src/lib/floriferous/floriferous-game.ts index 1af9fce..772dd36 100644 --- a/src/lib/floriferous/floriferous-game.ts +++ b/src/lib/floriferous/floriferous-game.ts @@ -1,4 +1,5 @@ -import type { FloriferousPlayer } from './floriferous-player'; +import type { FloriferousPlayer } from './floriferous-player.js'; +import { intlFormat as formatDate } from 'date-fns'; import { nanoid } from 'nanoid'; export interface FloriferousGameParams { @@ -28,11 +29,34 @@ export class FloriferousGame { }); } + get prettySummary(): string { + if (this._players.length === 0) { + return ''; + } + + const formattedDate = formatDate(this.playedTs, { + localeMatcher: 'best fit', + weekday: 'long', + day: 'numeric', + month: 'long', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + + const winnerStatement = `${this.winningPlayer.name} won with ${this.winningPlayer.score} points`; + const otherPlayerStatements = this.nonWinningsPlayers.map((player) => { + return `${player.name}: ${player.score} point${player.score === 1 ? '' : 's'}.`; + }); + + return [`${formattedDate}: ${winnerStatement}`, ...otherPlayerStatements].join('. '); + } + get players(): FloriferousPlayer[] { return this._players; } - get winner(): string | undefined { + private get winningPlayer(): FloriferousPlayer | undefined { if (this._players.length === 0) { return undefined; } @@ -45,9 +69,17 @@ export class FloriferousGame { return a.rowAtEndOfGame - b.rowAtEndOfGame; }); - return playersSortedByRowAtEndOfGame[0].name; + return playersSortedByRowAtEndOfGame[0]; } - return playersSortedByScore[0].name; + return playersSortedByScore[0]; + } + + private get nonWinningsPlayers(): FloriferousPlayer[] { + return this._players.filter((player) => player.name !== this.winner); + } + + get winner(): string | undefined { + return this.winningPlayer?.name; } } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index e99e968..56db26a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,6 +1,6 @@
diff --git a/src/routes/blog/+page.svelte b/src/routes/blog/+page.svelte index a9a882c..30369b0 100644 --- a/src/routes/blog/+page.svelte +++ b/src/routes/blog/+page.svelte @@ -1,6 +1,6 @@ + + +
+
+

Board Game Scoring & Ledgers

+

+ I like to play board games, but tallying up scores for some of them is a nightmare. I'm + building some tools to help me keep score. +

+ + +
+
diff --git a/src/routes/games/PreviousGameScores.svelte b/src/routes/games/PreviousGameScores.svelte new file mode 100644 index 0000000..c929201 --- /dev/null +++ b/src/routes/games/PreviousGameScores.svelte @@ -0,0 +1,46 @@ + + +
+ {#if isVisible} + +
    + {#each gameSummaries as summary} +
  • + {summary} +
  • + {/each} +
+ {:else} + + {/if} +
+ + diff --git a/src/routes/games/floriferous/+page.svelte b/src/routes/games/floriferous/+page.svelte index 129dd7d..5263254 100644 --- a/src/routes/games/floriferous/+page.svelte +++ b/src/routes/games/floriferous/+page.svelte @@ -1,15 +1,17 @@ -

Floriferous Scoring

-{#if previousGames.length > 0} -
-

Previous Games

-
    - {#each previousGames as game} -
  • - {Intl.DateTimeFormat('en-GB', { - weekday: 'long', - day: 'numeric', - month: 'long', - year: 'numeric', - hour: '2-digit', - minute: '2-digit' - }).format(game.playedTs)}: - {game.winner} Won -
  • - {/each} -
-
-{/if} + +
+

Floriferous Scoring

+

+ Floriferous is a board game published by Pencil First games, in which you find find joy in the + abundance of nature. +

-
-

Players

+
+

Players

- {#if players.length > 0} -
    - {#each players as player} -
  • - {player.name} ({player.score} points, finished on row {player.rowAtEndOfGame}) () -
  • - {/each} -
+ {#if players.length > 0} +
    + {#each players as player} +
  • + {player.name} ({player.score} points, finished on row {player.rowAtEndOfGame}) () +
  • + {/each} +
- {#if players.length > 1} - {#if isWinnerVisible} -

And the winner is:{game.winner}

-

Add to Ledger

+ {#if players.length > 1} + {#if isWinnerVisible} +

And the winner is:{game.winner}

+

Add to Ledger

- (apiPassword = event.detail)} /> + (apiPassword = event.detail)} /> - {#if apiPassword.length > 0} -

You can save this game in the Ledger

- + {#if apiPassword.length > 0} +

You can save this game in the Ledger

+ + {/if} + {:else} + {/if} - {:else} - {/if} + {:else} +

Add at least one player to get started

{/if} - {:else} -

Add at least one player to get started

- {/if} - {#if !isWinnerVisible} -

Add a New Player

- + {#if !isWinnerVisible} +

Add a New Player

+ + {/if} +
+ + {#if previousGames.length > 0} +
+

Previous Games

+ +
{/if} -
+
diff --git a/src/routes/games/types.ts b/src/routes/games/types.ts new file mode 100644 index 0000000..4e4897b --- /dev/null +++ b/src/routes/games/types.ts @@ -0,0 +1,3 @@ +export interface PreviousGame { + prettyString: string; +} diff --git a/src/styles/thomaswilson.css b/src/styles/thomaswilson.css index 91f016f..b3feb22 100644 --- a/src/styles/thomaswilson.css +++ b/src/styles/thomaswilson.css @@ -36,6 +36,12 @@ --font-size-sm: 0.875rem; --font-size-md: 1.25rem; --font-size-lg: 1.5rem; + + --btn-border: 0; + --btn-padding: var(--spacing-sm); + --btn-border-radius: 0.25rem; + --btn-font-size: 1.08rem; + --btn-text-decoration: none; } body { @@ -112,3 +118,16 @@ ul, ol { padding-left: var(--spacing-base); } + +.thomaswilson-button { + border: var(--btn-border); + padding: var(--btn-padding); + border-radius: var(--btn-border-radius); + font-size: var(--btn-font-size); + text-decoration: var(--btn-text-decoration); +} + +.thomaswilson-button:hover { + text-decoration: none; + cursor: pointer; +}