Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

poker-hand-evaluator-wasm

WenheLI87Apache-2.00.4.0TypeScript support: included

WebAssembly port of PokerHandEvaluator for fast poker hand evaluation

poker, evaluator, wasm, webassembly, poker-hand, texas-holdem, omaha

readme

PokerHandEvaluator-wasm

A WebAssembly port of Henry Lee's PokerHandEvaluator, an efficient poker hand evaluation algorithm and implementation.

npm version Test Publish to NPM

Features

  • Evaluates poker hands (5-card, 6-card, 7-card and Omaha) using WebAssembly for high performance in browsers and Node.js
  • Provides both numeric card ID interface and string-based card notation
  • Small footprint, suitable for web applications
  • Same fast and efficient algorithm as the original C/C++ implementation

Getting Started

Installation

You can install the prebuilt package directly from npm:

npm install poker-hand-evaluator-wasm

The npm package includes all the compiled WebAssembly files and JavaScript wrappers needed to use the library. No additional build steps are required for end-users.

For Developers: Cloning the Repository

This repository uses the original PokerHandEvaluator as a Git submodule. Use one of the following approaches:

# Clone the repository with submodules
git clone --recurse-submodules https://github.com/WenheLI/PokerHandEvaluator-wasm.git
cd PokerHandEvaluator-wasm

Option 2: Clone and then initialize submodules

If you already cloned the repository without the --recurse-submodules flag:

git clone https://github.com/WenheLI/PokerHandEvaluator-wasm.git
cd PokerHandEvaluator-wasm
git submodule init
git submodule update

Important: The Git submodules are only needed if you're building from source or contributing to development. If you're just using the npm package, you don't need to worry about Git submodules.

Building

To build the WebAssembly module, you need to have Emscripten installed. If you don't have it already, follow the Emscripten installation instructions.

# Set up Emscripten environment
source path/to/emsdk/emsdk_env.sh

# Build the WebAssembly module
emcmake cmake .
emmake make

This will generate phevaluator.js and phevaluator.wasm files in the dist directory.

Usage

In Node.js

You can import the module using either CommonJS or ES Modules.

CommonJS (require)

// Install the package
// npm install poker-hand-evaluator-wasm

const PHEvaluator = require('poker-hand-evaluator-wasm');

// Option 1: Using the simplified API (auto-initialization)
// The module is automatically initialized when required
// All API methods will throw if used before initialization completes

try {
  // Evaluate a hand directly (will throw if module is not ready yet)
  const result = PHEvaluator.evaluate(['As', 'Kh', 'Qd', 'Jc', '10s']);
  console.log("Royal Flush:", result.toString());
} catch (error) {
  console.error("Module not ready yet:", error.message);
}

// Option 2: Using async/await with the ready() method (recommended)
async function evaluateHands() {
  // Wait for the module to be fully initialized
  await PHEvaluator.ready();

  // Now safely use any of the module's functions
  const royalFlushHand = PHEvaluator.evaluate(['As', 'Kh', 'Qd', 'Jc', '10s']); // Royal Flush
  console.log("Royal Flush:", royalFlushHand.toString()); // "Straight Flush (Score: 1)"
  console.log("Hand Category:", royalFlushHand.categoryName()); // "Straight Flush"
  console.log("Category Value:", royalFlushHand.category); // 9
  console.log("Hand Score:", royalFlushHand.value); // 1

  // Evaluate using specific evaluator functions
  const straightFlushHand = PHEvaluator.evaluate7('Ah', 'Kh', 'Qh', 'Jh', 'Th', '9h', '8h');
  console.log("Straight Flush:", straightFlushHand.toString());

  // Evaluate a 6-card hand
  const sixCardHand = PHEvaluator.evaluate6('Ah', 'Kh', 'Qh', 'Jh', 'Th', '9h');
  console.log("Six-card hand:", sixCardHand.toString());

  // Evaluate Omaha hand (4 hole cards, 5 community cards)
  const omahaHand = PHEvaluator.evaluateOmaha(
      'Ah', 'Kh', 'Qh', 'Jd', '2c',  // Community cards
      'Th', '9h', '3c', '4d'         // Hole cards
  );
  console.log("Omaha Hand:", omahaHand.toString());

  // Compare two hands (lower score is better)
  const hand1 = PHEvaluator.evaluate5('Ah', 'Kh', 'Qh', 'Jh', 'Th'); // Royal Flush
  const hand2 = PHEvaluator.evaluate5('As', 'Ks', 'Qs', 'Js', 'Ts'); // Royal Flush (different suit)
  const hand3 = PHEvaluator.evaluate5('Ah', 'Ad', 'Ac', 'As', 'Kh'); // Four of a Kind

  if (hand1.value === hand2.value) {
      console.log("Hand 1 and Hand 2 are equal in strength");
  } else if (hand1.value < hand2.value) {
      console.log("Hand 1 is stronger than Hand 2");
  } else {
      console.log("Hand 2 is stronger than Hand 1");
  }
}

evaluateHands().catch(console.error);

// Option 3: Using the traditional Promise API
PHEvaluator.ready().then(function() {
  const hand = PHEvaluator.evaluate(['As', 'Ks', 'Qs', 'Js', 'Ts']);
  console.log("Royal Flush:", hand.toString());
}).catch(console.error);

// Option 4: Check if the module is already initialized
if (PHEvaluator.isReady()) {
  // Safe to use synchronously if already initialized
  const hand = PHEvaluator.evaluate(['As', 'Ks', 'Qs', 'Js', 'Ts']);
  console.log(hand.toString());
}

// Option 5: Access the raw WebAssembly module directly (advanced usage)
PHEvaluator.ready().then(function() {
  const rawModule = PHEvaluator.getRawModule();
  // Use the raw module API directly
  const Ah = new rawModule.Card(51);
  const Kh = new rawModule.Card(47);

});

ES Modules (import)

// Install the package
// npm install poker-hand-evaluator-wasm

import PHEvaluator from 'poker-hand-evaluator-wasm';
// You can also import the factory function directly if needed
// import PHEvaluator, { PokerHandEvaluatorWasmFactory } from 'poker-hand-evaluator-wasm';

// Option 1: Using the simplified API (auto-initialization)
// The module is automatically initialized when imported
// All API methods will throw if used before initialization completes

try {
  // Evaluate a hand directly (will throw if module is not ready yet)
  const result = PHEvaluator.evaluate(['As', 'Kh', 'Qd', 'Jc', '10s']);
  console.log("Royal Flush:", result.toString());
} catch (error) {
  console.error("Module not ready yet:", error.message);
}

// Option 2: Using async/await with the ready() method (recommended)
async function evaluateHands() {
  // Wait for the module to be fully initialized
  await PHEvaluator.ready();

  // Now safely use any of the module's functions
  const royalFlushHand = PHEvaluator.evaluate(['As', 'Ks', 'Qs', 'Js', 'Ts']); // Royal Flush
  console.log("Royal Flush:", royalFlushHand.toString());
}

evaluateHands().catch(console.error);

API Reference

The WebAssembly module exposes the following classes and functions:

Classes

Card

  • new Card(id) - Create a new Card object with the given card ID
  • Card.prototype.describeCard() - Get a string description of the card
  • Card.prototype.describeRank() - Get a string description of the card's rank
  • Card.prototype.describeSuit() - Get a string description of the card's suit
  • Card.prototype.id() - Get the numeric ID of the card
  • Card.prototype.toString() - Get a string representation of the card

HandRank

  • HandRank.prototype.value - The numeric score of the hand (lower is better)
  • HandRank.prototype.category - The category of the hand (1-9, where 9 is the best)
  • HandRank.prototype.categoryName() - Get the name of the hand category (e.g., "Straight Flush")
  • HandRank.prototype.toString() - Get a string representation of the hand with category and score

Functions Using Card Objects

  • evaluate5(a, b, c, d, e) - Evaluate a 5-card poker hand
  • evaluate6(a, b, c, d, e, f) - Evaluate a 6-card poker hand
  • evaluate7(a, b, c, d, e, f, g) - Evaluate a 7-card poker hand
  • evaluateOmaha(c1, c2, c3, c4, c5, h1, h2, h3, h4) - Evaluate an Omaha poker hand

Functions Using String Notation

  • evaluate5FromStrings(a, b, c, d, e) - Evaluate a 5-card poker hand using string notation
  • evaluate6FromStrings(a, b, c, d, e, f) - Evaluate a 6-card poker hand using string notation
  • evaluate7FromStrings(a, b, c, d, e, f, g) - Evaluate a 7-card poker hand using string notation
  • evaluateOmahaFromStrings(c1, c2, c3, c4, c5, h1, h2, h3, h4) - Evaluate an Omaha poker hand using string notation

Utility Functions

  • createCardFromString(cardStr) - Create a Card object from a string representation
  • createCardFromId(id) - Create a Card object from a numeric ID
  • cardStringToId(cardStr) - Convert a card string to its corresponding card ID

String notation format: <rank><suit> where:

  • Rank: 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K, A
  • Suit: c (clubs), d (diamonds), h (hearts), s (spades)

Examples: "Ah" (Ace of hearts), "Kd" (King of diamonds), "2c" (Two of clubs)

Demos & Examples

See the file in example folder

Project Structure

  • src/ - C++ WASM bindings
    • src/phevaluator_wasm.cpp - C++ wrapper for exposing the poker hand evaluator to JavaScript
    • src/include/ - Header files
  • lib/ - JavaScript wrapper code
  • dist/ - Compiled WebAssembly output
  • examples/ - Usage examples
  • __tests__/ - Test suite
  • PokerHandEvaluator/ - Git submodule of the original PokerHandEvaluator library
  • CMakeLists.txt - CMake build configuration for the WebAssembly module
  • .github/workflows/ - GitHub Actions workflows for testing and publishing

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License 2.0, the same as the original PokerHandEvaluator.