Skip to content

Repository files navigation

Tile Stakes: Technical Assessment

Tile Stakes is a browser-based Mahjong hand betting game built as an interview-friendly Angular assessment. The player predicts whether the next three-tile hand will be higher or lower while honor tile values shift after every result.

Setup

The project targets Node.js 24 LTS.

nvm use
npm install
npm start

Open http://localhost:4200.

npm test              # Run Vitest once
npm run build         # Create a production bundle

Video Walkthrough

Watch the walkthrough

Stack

  • Angular 22 with strict TypeScript and standalone components
  • Angular signals in one game store
  • Pure TypeScript game engine
  • Vitest for engine and persistence tests
  • Browser localStorage for the top-five leaderboard

Architecture

src/app/engine contains tile configuration, deck operations, rules, and session orchestration. These files have no Angular, storage, or UI imports and always return new state.

src/app/store/game-store.service.ts is the single bridge from the engine to Angular signals. Components render state and forward user intent to the store; they do not calculate rules.

src/app/store/leaderboard-repo.ts contains leaderboard rules and localStorage persistence. The game store is the only caller, so another persistence adapter can replace it later without touching the engine or components.

Each component under src/app/components has one visible responsibility: landing, leaderboard, table, controls, history, tiles, game over, or exit.

Rule assumptions

  • A hand always contains exactly three tiles.
  • The deck contains the standard 136 tiles: four copies of each Dragon, Wind, and numbered tile.
  • Number tile values equal their rank.
  • Each honor kind starts at 5 and changes independently.
  • Honor deltas apply once per honor tile copy across both compared hands: the previous current hand and the newly drawn hand.
  • Ties count as losses.
  • A win adds the next hand total; a loss subtracts it.
  • A draw-pile run-out means fewer than three tiles remain.
  • The first two run-outs add a fresh 136-tile deck to all available tiles; the third ends the game without resolving the pending bet.
  • If an honor reaches 0 or 10, remaining honor deltas stop, the resolved round is recorded, and the session ends.
  • A leaderboard score must be strictly greater than fifth place when five entries already exist.

How to play

The player starts with a visible three-tile hand and total. Each round, they bet whether the next three-tile hand will be higher or lower than the current total.

After the bet resolves, the next hand becomes the new current hand. Number tiles keep their face value, while Dragon and Wind values shift over time based on wins and losses. The run ends when an honor value reaches 0 or 10, or when the draw pile runs out for the third time.

Keyboard and accessibility

  • H: Bet Higher
  • L: Bet Lower
  • Esc: Exit to the landing page

Shortcuts are ignored while a text field has focus. Controls use semantic HTML, visible focus indicators, non-color status labels, an announced result region, WCAG 2.2 AA contrast, and reduced-motion behavior.

Testing

The suite covers the 136-tile composition, four physical copies per tile kind, unique physical IDs, complete draws, both permitted reshuffles, scoring, tie handling, per-copy honor updates across both compared hands, boundary termination, session transitions, third run-out behavior, persistence, and name normalization. A seeded simulation runs 1,000 games and verifies tile accounting, complete hands, bounded honor values, and eventual game-over.

Future extensions

  • Treat ties as a push
  • Make hand size configurable
  • Add selectable scoring modes
  • Replace localStorage with a Node.js and MongoDB leaderboard API
  • Add alternate tile sets or difficulty modes
  • Persist an active session across refreshes

AI usage

AI assistance was used to accelerate scaffolding, UI iteration, and test drafting. The game rules, edge-case handling, architecture boundaries, and final code review were manually directed and reviewed.

Assets

Mahjong tile SVGs are sourced from the Black set in FluffyStuff/riichi-mahjong-tiles. The project serves the selected files from public/tiles/black through static URL paths such as /tiles/black/Man1.svg.

Source and public-domain details are recorded in public/tiles/ATTRIBUTION.md.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages