@pokertools/evaluator 1.0.1 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,124 +1,250 @@
1
- # @pokertools/evaluator
1
+ # 🃏 @pokertools/evaluator
2
+
3
+ > **High-performance poker hand evaluator for 5, 6, and 7 card hands**
2
4
 
3
5
  [![npm version](https://img.shields.io/npm/v/@pokertools/evaluator.svg)](https://www.npmjs.com/package/@pokertools/evaluator)
4
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
5
8
 
6
- A lightning-fast, strongly-typed Poker Hand Evaluator for Node.js and the browser.
9
+ A blazing-fast poker hand evaluator using **perfect hash tables** and **lookup tables** for O(1) hand evaluation. Designed for Monte Carlo simulations and real-time poker applications.
7
10
 
8
- Capable of evaluating **over 16 million 7-card hands per second** on a standard CPU. This library uses a Perfect Hash algorithm (based on Cactus Kev/Paul Senzee) optimized specifically for the V8 JavaScript engine.
11
+ ---
9
12
 
10
- ## 🚀 Features
13
+ ## Performance
11
14
 
12
- - **Extreme Performance:** ~17M evaluations/sec (7-card hands).
13
- - **Zero Garbage Collection:** Uses static memory buffers to prevent GC overhead during Monte Carlo simulations.
14
- - **Flexible:** Supports 5, 6, and 7 card hands.
15
- - **TypeScript:** Written in strict TypeScript with full type definitions.
16
- - **Lightweight:** Zero runtime dependencies.
15
+ ```
16
+ ┌─────────────────────────────────────────────────────────────────────────────┐
17
+ │ BENCHMARK RESULTS │
18
+ ├─────────────────────────────────────────────────────────────────────────────┤
19
+ │ 5 cards: ~15-20 million evaluations/second │
20
+ │ 6 cards: ~12-15 million evaluations/second │
21
+ │ 7 cards: ~10-12 million evaluations/second │
22
+ ├─────────────────────────────────────────────────────────────────────────────┤
23
+ │ Memory footprint: ~2.5 MB (lookup tables) │
24
+ │ Algorithm: Perfect hash + suit hash + lookup tables │
25
+ │ Complexity: O(1) per evaluation │
26
+ └─────────────────────────────────────────────────────────────────────────────┘
27
+ ```
17
28
 
18
- ## ⚡ Benchmarks
29
+ ---
19
30
 
20
- Comparison of 7-card hand evaluation speed (Node.js V8):
31
+ ## 📦 Installation
21
32
 
22
- | Library | Input Type | Speed (Hands/Sec) | Relative Speed |
23
- | :------------------------ | :---------- | :---------------- | :------------- |
24
- | **@pokertools/evaluator** | **Integer** | **~17,900,000** | **100%** |
25
- | phe | Integer | ~16,550,000 | 92.5% |
26
- | poker-evaluator | String | ~1,390,000 | 7.7% |
27
- | pokersolver | String | ~73,000 | 0.4% |
33
+ ```bash
34
+ npm install @pokertools/evaluator
35
+ ```
28
36
 
29
- ### Raw Output
37
+ ```bash
38
+ yarn add @pokertools/evaluator
39
+ ```
30
40
 
31
- ```text
32
- 🃏 Starting Benchmark: 1000 random 7-card hands per cycle
33
- ----------------------------------------------------------------
34
- phe (Int) | 16,574,257 hands/sec | ±2.26%
35
- poker-evaluator (Str) | 1,375,495 hands/sec | ±0.33%
36
- pokersolver (Str) | 70,980 hands/sec | ±0.70%
37
- @pokertools (Int) | 17,915,292 hands/sec | ±1.56%
38
- ----------------------------------------------------------------
39
- 🚀 WINNER: @pokertools (Int)
41
+ ```bash
42
+ pnpm add @pokertools/evaluator
40
43
  ```
41
44
 
42
- _Benchmarks run on an M1 Air. Higher is better._
45
+ ---
43
46
 
44
- ## 📦 Installation
47
+ ## 🚀 Quick Start
45
48
 
46
- ```bash
47
- npm install @pokertools/evaluator
49
+ ```typescript
50
+ import {
51
+ evaluate,
52
+ evaluateStrings,
53
+ evaluateBoard,
54
+ rank,
55
+ rankBoard,
56
+ rankDescription,
57
+ HandRank,
58
+ } from "@pokertools/evaluator";
59
+
60
+ // Method 1: Evaluate card strings
61
+ const score = evaluateStrings(["As", "Kh", "Qd", "Jc", "Ts"]);
62
+ console.log(score); // Lower score = better hand
63
+
64
+ // Method 2: Evaluate board string
65
+ const score2 = evaluateBoard("As Kh Qd Jc Ts");
66
+
67
+ // Method 3: Get hand rank category
68
+ const handRank = rankBoard("As Kh Qd Jc Ts");
69
+ console.log(handRank); // 4 (Straight)
70
+ console.log(rankDescription(handRank)); // "Straight"
71
+ ```
72
+
73
+ ---
74
+
75
+ ## 📖 API Reference
76
+
77
+ ### Core Functions
78
+
79
+ #### `evaluate(codes: number[]): number`
80
+
81
+ Evaluates 5, 6, or 7 card integer codes. Returns a strength score where **lower is better**.
82
+
83
+ ```typescript
84
+ import { evaluate, getCardCode } from "@pokertools/evaluator";
85
+
86
+ // Convert cards to codes manually
87
+ const codes = [
88
+ getCardCode("As"), // 48
89
+ getCardCode("Kh"), // 45
90
+ getCardCode("Qd"), // 42
91
+ getCardCode("Jc"), // 39
92
+ getCardCode("Ts"), // 32
93
+ ];
94
+
95
+ const score = evaluate(codes);
96
+ // Royal flush will have score = 1 (best possible)
48
97
  ```
49
98
 
50
- ## 📖 Usage
99
+ ---
51
100
 
52
- ### 1. Basic Usage (Strings)
101
+ #### `evaluateStrings(cards: string[]): number`
53
102
 
54
- If you are building a UI or simple game logic, string inputs are easiest to work with.
103
+ Evaluates an array of card strings. Convenient but slightly slower than `evaluate()` due to parsing overhead.
55
104
 
56
105
  ```typescript
57
- import { evaluateBoard, rankBoard, rankDescription } from "@pokertools/evaluator";
106
+ import { evaluateStrings } from "@pokertools/evaluator";
107
+
108
+ // 5-card hand
109
+ const score5 = evaluateStrings(["As", "Ks", "Qs", "Js", "Ts"]);
58
110
 
59
- // 1. Get a raw strength score (lower is better)
60
- const score = evaluateBoard("Ah Kh Qh Jh Th 2c 3c");
61
- console.log(score); // 1 (Royal Flush is the lowest/best number)
111
+ // 6-card hand (best 5 of 6)
112
+ const score6 = evaluateStrings(["As", "Ks", "Qs", "Js", "Ts", "2h"]);
62
113
 
63
- // 2. Get the Rank Category (Enum)
64
- const rank = rankBoard("Ah As Ks Kd Qs Qd 2c");
65
- console.log(rankDescription(rank)); // "Two Pair"
114
+ // 7-card hand (Texas Hold'em)
115
+ const score7 = evaluateStrings(["As", "Ks", "Qs", "Js", "Ts", "2h", "3c"]);
66
116
  ```
67
117
 
68
- ### 2. High-Performance Usage (Integers)
118
+ ---
69
119
 
70
- If you are building an Equity Calculator or AI Solver, you should convert cards to integers **once** and pass integers around your system. This creates a 12x performance boost by skipping string parsing.
120
+ #### `evaluateBoard(board: string): number`
121
+
122
+ Evaluates a space-separated board string.
71
123
 
72
124
  ```typescript
73
- import { evaluate, getCardCode, rank, HandRank } from "@pokertools/evaluator";
125
+ import { evaluateBoard } from "@pokertools/evaluator";
74
126
 
75
- // Convert strings to integers once
76
- const holeCards = [getCardCode("As"), getCardCode("Ah")];
77
- const board = [getCardCode("Ks"), getCardCode("Kh"), getCardCode("Qs")];
127
+ // Standard Texas Hold'em (2 hole + 5 community)
128
+ const score = evaluateBoard("As Ks Qs Js Ts 2h 3c");
78
129
 
79
- // Combine arrays (Spread operator is fast enough for small arrays)
80
- const hand = [...holeCards, ...board];
130
+ // Just the board (5 community cards)
131
+ const boardScore = evaluateBoard("As Ks Qs Js Ts");
81
132
 
82
- // Evaluate
83
- const strength = evaluate(hand);
133
+ // Extra whitespace is handled
134
+ const score2 = evaluateBoard("As Ks Qs Js Ts");
135
+ ```
84
136
 
85
- // Check Rank
86
- if (rank(hand) === HandRank.FullHouse) {
87
- console.log("We have a boat!");
88
- }
137
+ ---
138
+
139
+ #### `rank(codes: number[]): HandRank`
140
+
141
+ Returns the hand rank category (0-8) for card integer codes.
142
+
143
+ ```typescript
144
+ import { rank, getCardCodes, HandRank } from "@pokertools/evaluator";
145
+
146
+ const codes = getCardCodes(["As", "Ah", "Ad", "Ac", "Kh"]);
147
+ const handRank = rank(codes);
148
+
149
+ console.log(handRank === HandRank.FourOfAKind); // true
89
150
  ```
90
151
 
91
- ## 📚 API Reference
152
+ ---
92
153
 
93
- ### Core Functions
154
+ #### `rankBoard(board: string): HandRank`
94
155
 
95
- #### `evaluate(codes: number[]): number`
156
+ Returns the hand rank category for a board string.
96
157
 
97
- The fastest evaluation method. Accepts an array of 5, 6, or 7 integers. Returns a raw score (lower is better).
158
+ ```typescript
159
+ import { rankBoard, HandRank } from "@pokertools/evaluator";
98
160
 
99
- - Royal Flush: 1
100
- - ...
101
- - Worst High Card: 7462
161
+ const handRank = rankBoard("As Ks Qs Js Ts");
162
+ console.log(handRank === HandRank.StraightFlush); // true
163
+ ```
102
164
 
103
- #### `evaluateStrings(cards: string[]): number`
165
+ ---
166
+
167
+ #### `rankDescription(rank: HandRank): string`
104
168
 
105
- Helper to evaluate an array of strings like `['Ah', 'Td', ...]`.
169
+ Returns the human-readable name of a hand rank.
106
170
 
107
- #### `evaluateBoard(board: string): number`
171
+ ```typescript
172
+ import { rankBoard, rankDescription } from "@pokertools/evaluator";
108
173
 
109
- Helper to evaluate a space-separated string like `"Ah Td 2c"`.
174
+ const handRank = rankBoard("As Ah Ad Kh Kd");
175
+ const name = rankDescription(handRank);
176
+ console.log(name); // "Full House"
177
+ ```
110
178
 
111
- ### Ranking Helpers
179
+ ---
112
180
 
113
- #### `rank(codes: number[]): HandRank`
181
+ ### Utility Functions
182
+
183
+ #### `getCardCode(cardStr: string): number`
184
+
185
+ Converts a 2-character card string to an integer code.
186
+
187
+ ```typescript
188
+ import { getCardCode } from "@pokertools/evaluator";
189
+
190
+ const aceOfSpades = getCardCode("As"); // 48
191
+ const kingOfHearts = getCardCode("Kh"); // 45
192
+ const tenOfDiamonds = getCardCode("Td"); // 34
193
+ const twoOfClubs = getCardCode("2c"); // 3
194
+ ```
195
+
196
+ **Card Format:**
197
+
198
+ ```
199
+ ┌─────────────────────────────────────────────────────────────────┐
200
+ │ CARD FORMAT: [Rank][Suit] │
201
+ ├─────────────────────────────────────────────────────────────────┤
202
+ │ Ranks: 2, 3, 4, 5, 6, 7, 8, 9, T, J, Q, K, A │
203
+ │ Suits: s (♠ spades), h (♥ hearts), d (♦ diamonds), c (♣ clubs) │
204
+ ├─────────────────────────────────────────────────────────────────┤
205
+ │ ⚠️ Rank must be UPPERCASE (T, J, Q, K, A) │
206
+ │ ⚠️ Suit must be LOWERCASE (s, h, d, c) │
207
+ └─────────────────────────────────────────────────────────────────┘
208
+ ```
209
+
210
+ ---
114
211
 
115
- Returns the `HandRank` enum (0-8) for a set of card integers.
212
+ #### `getCardCodes(cards: string[]): number[]`
116
213
 
117
- #### `HandRank` (Enum)
214
+ Converts an array of card strings to integer codes.
118
215
 
119
216
  ```typescript
120
- enum HandRank {
121
- StraightFlush = 0,
217
+ import { getCardCodes } from "@pokertools/evaluator";
218
+
219
+ const codes = getCardCodes(["As", "Kh", "Qd", "Jc", "Ts"]);
220
+ // [48, 45, 42, 39, 32]
221
+ ```
222
+
223
+ ---
224
+
225
+ #### `stringifyCardCode(code: number): string`
226
+
227
+ Converts an integer code back to a card string.
228
+
229
+ ```typescript
230
+ import { stringifyCardCode } from "@pokertools/evaluator";
231
+
232
+ stringifyCardCode(48); // "As"
233
+ stringifyCardCode(0); // "2s"
234
+ stringifyCardCode(51); // "Ac"
235
+ ```
236
+
237
+ ---
238
+
239
+ ### Constants & Types
240
+
241
+ #### `HandRank` Enum
242
+
243
+ ```typescript
244
+ import { HandRank } from "@pokertools/evaluator";
245
+
246
+ const enum HandRank {
247
+ StraightFlush = 0, // 🏆 Best
122
248
  FourOfAKind = 1,
123
249
  FullHouse = 2,
124
250
  Flush = 3,
@@ -126,34 +252,356 @@ enum HandRank {
126
252
  ThreeOfAKind = 5,
127
253
  TwoPair = 6,
128
254
  OnePair = 7,
129
- HighCard = 8,
255
+ HighCard = 8, // Worst
130
256
  }
131
257
  ```
132
258
 
133
- #### `rankDescription(rank: HandRank): string`
259
+ **Hand Rank Distribution (5-card hands):**
260
+
261
+ | Rank | Name | Count | Probability |
262
+ | ---- | --------------- | --------- | ----------- |
263
+ | 0 | Straight Flush | 40 | 0.00154% |
264
+ | 1 | Four of a Kind | 624 | 0.02401% |
265
+ | 2 | Full House | 3,744 | 0.14406% |
266
+ | 3 | Flush | 5,108 | 0.19654% |
267
+ | 4 | Straight | 10,200 | 0.39246% |
268
+ | 5 | Three of a Kind | 54,912 | 2.11285% |
269
+ | 6 | Two Pair | 123,552 | 4.75390% |
270
+ | 7 | One Pair | 1,098,240 | 42.25690% |
271
+ | 8 | High Card | 1,302,540 | 50.11774% |
272
+
273
+ ---
274
+
275
+ #### `HAND_RANK_DESCRIPTIONS`
276
+
277
+ Map of hand rank enums to human-readable names.
278
+
279
+ ```typescript
280
+ import { HAND_RANK_DESCRIPTIONS, HandRank } from "@pokertools/evaluator";
281
+
282
+ console.log(HAND_RANK_DESCRIPTIONS[HandRank.FullHouse]); // "Full House"
283
+ console.log(HAND_RANK_DESCRIPTIONS[HandRank.StraightFlush]); // "Straight Flush"
284
+ ```
285
+
286
+ ---
287
+
288
+ ## 🎯 Score System
289
+
290
+ The evaluator returns a **score** where **lower is better**:
291
+
292
+ ```
293
+ Score Range Hand Type
294
+ ───────────────────────────────────────
295
+ 1-10 Straight Flush (Royal Flush = 1)
296
+ 11-166 Four of a Kind
297
+ 167-322 Full House
298
+ 323-1599 Flush
299
+ 1600-1609 Straight
300
+ 1610-2467 Three of a Kind
301
+ 2468-3325 Two Pair
302
+ 3326-6185 One Pair
303
+ 6186-7462 High Card
304
+ ```
305
+
306
+ ### Comparing Hands
307
+
308
+ ```typescript
309
+ import { evaluateStrings } from "@pokertools/evaluator";
310
+
311
+ const royalFlush = evaluateStrings(["As", "Ks", "Qs", "Js", "Ts"]);
312
+ const straightFlush = evaluateStrings(["9h", "8h", "7h", "6h", "5h"]);
313
+ const fourOfAKind = evaluateStrings(["Ac", "Ah", "Ad", "As", "Kh"]);
314
+ const fullHouse = evaluateStrings(["Kh", "Kd", "Ks", "Qh", "Qd"]);
315
+
316
+ // Lower score wins
317
+ console.log(royalFlush); // 1
318
+ console.log(straightFlush); // 2-10
319
+ console.log(fourOfAKind); // 11-166
320
+ console.log(fullHouse); // 167-322
321
+
322
+ // Comparison
323
+ console.log(royalFlush < straightFlush); // true (royal beats straight flush)
324
+ console.log(fourOfAKind < fullHouse); // true (quads beat boat)
325
+ ```
326
+
327
+ ---
328
+
329
+ ## 🔧 Advanced Usage
330
+
331
+ ### Monte Carlo Simulation
332
+
333
+ ```typescript
334
+ import { evaluate } from "@pokertools/evaluator";
335
+
336
+ function monteCarloEquity(
337
+ heroHand: number[],
338
+ villainHand: number[],
339
+ board: number[],
340
+ simulations: number = 100000
341
+ ): number {
342
+ let wins = 0;
343
+ const deck = createDeck().filter(
344
+ (c) => !heroHand.includes(c) && !villainHand.includes(c) && !board.includes(c)
345
+ );
346
+
347
+ for (let i = 0; i < simulations; i++) {
348
+ const shuffled = shuffle(deck);
349
+ const remainingCards = 5 - board.length;
350
+ const runout = [...board, ...shuffled.slice(0, remainingCards)];
351
+
352
+ const heroScore = evaluate([...heroHand, ...runout]);
353
+ const villainScore = evaluate([...villainHand, ...runout]);
354
+
355
+ if (heroScore < villainScore) wins++;
356
+ else if (heroScore === villainScore) wins += 0.5;
357
+ }
358
+
359
+ return wins / simulations;
360
+ }
361
+ ```
362
+
363
+ ### Hand Range Analysis
364
+
365
+ ```typescript
366
+ import { evaluate, getCardCodes } from "@pokertools/evaluator";
367
+
368
+ function analyzeRange(
369
+ holeCards: string[],
370
+ board: string[],
371
+ range: string[][]
372
+ ): { wins: number; ties: number; losses: number } {
373
+ const heroCodes = getCardCodes(holeCards);
374
+ const boardCodes = getCardCodes(board);
375
+ const heroScore = evaluate([...heroCodes, ...boardCodes]);
376
+
377
+ let wins = 0,
378
+ ties = 0,
379
+ losses = 0;
380
+
381
+ for (const hand of range) {
382
+ const villainCodes = getCardCodes(hand);
383
+ const villainScore = evaluate([...villainCodes, ...boardCodes]);
384
+
385
+ if (heroScore < villainScore) wins++;
386
+ else if (heroScore === villainScore) ties++;
387
+ else losses++;
388
+ }
389
+
390
+ return { wins, ties, losses };
391
+ }
392
+ ```
393
+
394
+ ### Finding Best 5 from 7
395
+
396
+ The evaluator automatically finds the best 5-card hand from 6 or 7 cards:
397
+
398
+ ```typescript
399
+ import { evaluateStrings, rankBoard, rankDescription } from "@pokertools/evaluator";
400
+
401
+ // 7 cards: 2 hole cards + 5 community cards
402
+ const cards = ["As", "Kh", "Qs", "Js", "Ts", "2c", "3d"];
403
+ const score = evaluateStrings(cards);
404
+ const handRank = rankBoard(cards.join(" "));
405
+
406
+ console.log(rankDescription(handRank)); // "Straight" (A-K-Q-J-T)
407
+ // The 2c and 3d are ignored - best 5 cards selected automatically
408
+ ```
134
409
 
135
- Returns human-readable strings like "Full House" or "High Card".
410
+ ---
411
+
412
+ ## 🏗️ Architecture
413
+
414
+ ```
415
+ ┌─────────────────────────────────────────────────────────────────────────────┐
416
+ │ EVALUATOR ARCHITECTURE │
417
+ └─────────────────────────────────────────────────────────────────────────────┘
418
+
419
+ ┌──────────────┐
420
+ │ Input Cards │ "As", "Kh", "Qd"...
421
+ └──────┬───────┘
422
+
423
+
424
+ ┌──────────────┐
425
+ │ Card Parser │ getCardCode() → Integer encoding
426
+ │ │ Format: (RankIndex << 2) | SuitIndex
427
+ └──────┬───────┘
428
+ │ [48, 45, 42, 39, 32]
429
+
430
+ ┌──────────────────────────────────────────────────────────────┐
431
+ │ EVALUATOR CORE │
432
+ ├──────────────────────────────────────────────────────────────┤
433
+ │ │
434
+ │ ┌────────────────┐ ┌────────────────┐ │
435
+ │ │ Suit Hash │────▶│ Flush Check │ │
436
+ │ │ Detection │ │ SUITS_HASH[] │ │
437
+ │ └────────────────┘ └───────┬────────┘ │
438
+ │ │ │
439
+ │ ┌───────────────────────┼───────────────────┐ │
440
+ │ │ FLUSH │ NO FLUSH │ │
441
+ │ ▼ ▼ │ │
442
+ │ ┌────────────────┐ ┌────────────────┐ │ │
443
+ │ │ FLUSH_LOOKUP[] │ │ Quinary Hash │ │ │
444
+ │ │ 8192 entries │ │ hashQuinary() │ │ │
445
+ │ └───────┬────────┘ └───────┬────────┘ │ │
446
+ │ │ │ │ │
447
+ │ │ ┌───────┴────────┐ │ │
448
+ │ │ ▼ ▼ ▼ │ │
449
+ │ │ ┌─────────┬─────────┬─────────┐ │ │
450
+ │ │ │NO_FLUSH │NO_FLUSH │NO_FLUSH │ │ │
451
+ │ │ │ _5 │ _6 │ _7 │ │ │
452
+ │ │ │ 49205 │ 246520 │ 1070190 │ │ │
453
+ │ │ └────┬────┴────┬────┴────┬────┘ │ │
454
+ │ │ │ │ │ │ │
455
+ │ └─────────────┴─────────┴─────────┘ │ │
456
+ │ │ │ │
457
+ └──────────────────────────────┼──────────────────────┘ │
458
+ │ │
459
+ ▼ │
460
+ ┌──────────────┐ │
461
+ │ SCORE │ 1-7462 │
462
+ │ (lower=better)│ │
463
+ └──────────────┘ │
464
+ ```
136
465
 
137
466
  ### Card Encoding
138
467
 
139
- #### `getCardCode(cardStr: string): number`
468
+ ```
469
+ Card Integer = (RankIndex << 2) | SuitIndex
140
470
 
141
- Converts a card string (e.g., `"Ah"`) into the optimized integer format used by this library.
471
+ Rank Index: 2=0, 3=1, 4=2, 5=3, 6=4, 7=5, 8=6, 9=7, T=8, J=9, Q=10, K=11, A=12
472
+ Suit Index: s=0, h=1, d=2, c=3
142
473
 
143
- #### `stringifyCardCode(code: number): string`
474
+ Examples:
475
+ "2s" = (0 << 2) | 0 = 0
476
+ "2h" = (0 << 2) | 1 = 1
477
+ "As" = (12 << 2) | 0 = 48
478
+ "Ac" = (12 << 2) | 3 = 51
479
+ ```
480
+
481
+ ### Lookup Tables
482
+
483
+ | Table | Size | Purpose |
484
+ | -------------- | --------- | ----------------------------- |
485
+ | `FLUSH_LOOKUP` | 8,192 | Direct lookup for flush hands |
486
+ | `NO_FLUSH_5` | 49,205 | 5-card non-flush hands |
487
+ | `NO_FLUSH_6` | 246,520 | 6-card non-flush hands |
488
+ | `NO_FLUSH_7` | 1,070,190 | 7-card non-flush hands |
489
+ | `SUITS_HASH` | 8,192 | Suit hash detection |
490
+ | `DP_MATRIX` | ~3,500 | Perfect hash calculation |
491
+
492
+ ---
493
+
494
+ ## ⚠️ Important Notes
495
+
496
+ ### Thread Safety
497
+
498
+ ```typescript
499
+ /**
500
+ * ⚠️ NOT THREAD-SAFE / NOT RE-ENTRANT
501
+ *
502
+ * The evaluator uses static buffers for performance.
503
+ *
504
+ * ✅ SAFE:
505
+ * - Sequential calls
506
+ * - Async/await (yields between calls)
507
+ * - Different JavaScript contexts
508
+ *
509
+ * ❌ UNSAFE:
510
+ * - Recursive evaluate() calls
511
+ * - SharedArrayBuffer / Worker threads
512
+ * - Calling evaluate() from within evaluate()
513
+ */
514
+
515
+ // ✅ Safe: Sequential
516
+ const a = evaluate(hand1);
517
+ const b = evaluate(hand2);
518
+
519
+ // ✅ Safe: Async
520
+ for (const hand of hands) {
521
+ const score = evaluate(hand);
522
+ await saveToDatabase(score);
523
+ }
524
+
525
+ // ❌ UNSAFE: Recursive
526
+ function bad(cards) {
527
+ if (cards.length > 7) {
528
+ return evaluate(cards.slice(0, 7)); // DON'T DO THIS
529
+ }
530
+ return evaluate(cards);
531
+ }
532
+ ```
533
+
534
+ ### Input Validation
535
+
536
+ The evaluator does **not** validate for duplicate cards. Duplicate card detection is the responsibility of the game engine.
537
+
538
+ ```typescript
539
+ // ❌ No error thrown, but undefined behavior
540
+ evaluate([0, 0, 0, 0, 0]); // 5 identical cards
541
+
542
+ // ✅ Validate before calling
543
+ function safeEvaluate(codes: number[]): number {
544
+ const unique = new Set(codes);
545
+ if (unique.size !== codes.length) {
546
+ throw new Error("Duplicate cards detected");
547
+ }
548
+ return evaluate(codes);
549
+ }
550
+ ```
551
+
552
+ ### Card Format Requirements
553
+
554
+ ```typescript
555
+ // ✅ Correct format
556
+ getCardCode("As"); // Ace of spades
557
+ getCardCode("Td"); // Ten of diamonds
558
+ getCardCode("2c"); // Two of clubs
559
+
560
+ // ❌ Wrong format
561
+ getCardCode("as"); // Error: lowercase rank
562
+ getCardCode("AS"); // Error: uppercase suit
563
+ getCardCode("10h"); // Error: use "T" for 10
564
+ getCardCode("1s"); // Error: no "1" rank
565
+ ```
566
+
567
+ ---
568
+
569
+ ## 📊 Combinatorics Verification
570
+
571
+ The evaluator has been verified against all possible hand combinations:
572
+
573
+ | Cards | Combinations | Verified |
574
+ | ----- | ------------ | -------- |
575
+ | 5 | 2,598,960 | ✅ |
576
+ | 6 | 20,358,520 | ✅ |
577
+ | 7 | 133,784,560 | ✅ |
578
+
579
+ All hand frequencies match mathematically proven distributions.
580
+
581
+ ---
582
+
583
+ ## 🔗 Related Packages
584
+
585
+ | Package | Description |
586
+ | ------------------------------- | ---------------------- |
587
+ | [@pokertools/types](../types) | Type definitions |
588
+ | [@pokertools/engine](../engine) | Game state machine |
589
+ | [@pokertools/bench](../bench) | Performance benchmarks |
590
+
591
+ ---
144
592
 
145
- Converts an integer back into a readable string.
593
+ ## 📄 License
146
594
 
147
- ## 🧮 Algorithm
595
+ MIT © A.Aurelius
148
596
 
149
- This library implements the **Perfect Hash** algorithm.
597
+ ---
150
598
 
151
- 1. It first checks for a Flush using a bitmask OR operation.
152
- 2. If no flush, it calculates a unique prime-product hash (Quinary) based on the rank counts.
153
- 3. This hash is used as an index into a pre-computed DAG (Directed Acyclic Graph) lookup table to immediately return the hand strength.
599
+ ## 🙏 Credits
154
600
 
155
- This approach avoids expensive sorting or pattern matching operations found in slower libraries.
601
+ Algorithm based on the perfect hash technique pioneered by:
156
602
 
157
- ## License
603
+ - Cactus Kev's Poker Hand Evaluator
604
+ - Two Plus Two evaluator
605
+ - Senzee's 5-card evaluator
158
606
 
159
- MIT
607
+ Optimized for TypeScript with lookup table compression and static buffer reuse.
@@ -0,0 +1 @@
1
+ {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.dom.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../../node_modules/typescript/lib/lib.scripthost.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2025.float16.d.ts","../../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/typescript/lib/lib.es2020.full.d.ts","../src/tables/bit-masks.ts","../src/tables/dp.ts","../src/tables/flush.ts","../src/tables/no-flush-5.ts","../src/tables/no-flush-6.ts","../src/tables/no-flush-7.ts","../src/core/hash.ts","../src/core/evaluator.ts","../src/utils/card.ts","../src/models/hand-rank.ts","../src/index.ts","../../../node_modules/@types/node/globals.typedarray.d.ts","../../../node_modules/@types/node/buffer.buffer.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../node_modules/@types/node/web-globals/blob.d.ts","../../../node_modules/@types/node/web-globals/console.d.ts","../../../node_modules/@types/node/web-globals/crypto.d.ts","../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../node_modules/@types/node/web-globals/encoding.d.ts","../../../node_modules/@types/node/web-globals/events.d.ts","../../../node_modules/undici-types/utility.d.ts","../../../node_modules/undici-types/header.d.ts","../../../node_modules/undici-types/readable.d.ts","../../../node_modules/undici-types/fetch.d.ts","../../../node_modules/undici-types/formdata.d.ts","../../../node_modules/undici-types/connector.d.ts","../../../node_modules/undici-types/client-stats.d.ts","../../../node_modules/undici-types/client.d.ts","../../../node_modules/undici-types/errors.d.ts","../../../node_modules/undici-types/dispatcher.d.ts","../../../node_modules/undici-types/global-dispatcher.d.ts","../../../node_modules/undici-types/global-origin.d.ts","../../../node_modules/undici-types/pool-stats.d.ts","../../../node_modules/undici-types/pool.d.ts","../../../node_modules/undici-types/handlers.d.ts","../../../node_modules/undici-types/balanced-pool.d.ts","../../../node_modules/undici-types/round-robin-pool.d.ts","../../../node_modules/undici-types/h2c-client.d.ts","../../../node_modules/undici-types/agent.d.ts","../../../node_modules/undici-types/dispatcher1-wrapper.d.ts","../../../node_modules/undici-types/mock-interceptor.d.ts","../../../node_modules/undici-types/mock-call-history.d.ts","../../../node_modules/undici-types/mock-agent.d.ts","../../../node_modules/undici-types/mock-client.d.ts","../../../node_modules/undici-types/mock-pool.d.ts","../../../node_modules/undici-types/snapshot-agent.d.ts","../../../node_modules/undici-types/mock-errors.d.ts","../../../node_modules/undici-types/proxy-agent.d.ts","../../../node_modules/undici-types/socks5-proxy-agent.d.ts","../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../node_modules/undici-types/retry-handler.d.ts","../../../node_modules/undici-types/retry-agent.d.ts","../../../node_modules/undici-types/api.d.ts","../../../node_modules/undici-types/cache-interceptor.d.ts","../../../node_modules/undici-types/interceptors.d.ts","../../../node_modules/undici-types/util.d.ts","../../../node_modules/undici-types/cookies.d.ts","../../../node_modules/undici-types/patch.d.ts","../../../node_modules/undici-types/websocket.d.ts","../../../node_modules/undici-types/eventsource.d.ts","../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../node_modules/undici-types/content-type.d.ts","../../../node_modules/undici-types/cache.d.ts","../../../node_modules/undici-types/index.d.ts","../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../node_modules/@types/node/web-globals/importmeta.d.ts","../../../node_modules/@types/node/web-globals/messaging.d.ts","../../../node_modules/@types/node/web-globals/navigator.d.ts","../../../node_modules/@types/node/web-globals/performance.d.ts","../../../node_modules/@types/node/web-globals/storage.d.ts","../../../node_modules/@types/node/web-globals/streams.d.ts","../../../node_modules/@types/node/web-globals/timers.d.ts","../../../node_modules/@types/node/web-globals/url.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/inspector.generated.d.ts","../../../node_modules/@types/node/inspector/promises.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/buffer/index.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/path/posix.d.ts","../../../node_modules/@types/node/path/win32.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/quic.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/sea.d.ts","../../../node_modules/@types/node/sqlite.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/iter.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/test/reporters.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/util/types.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/zlib/iter.d.ts","../../../node_modules/@types/node/index.d.ts"],"fileIdsList":[[66,128,129,131,139,143,146,148,149,150,163],[66,130,131,139,143,146,148,149,150,163],[131,139,143,146,148,149,150,163],[66,131,139,143,146,148,149,150,163,172],[66,131,132,137,139,142,143,146,148,149,150,152,163,168,181],[66,131,132,133,139,142,143,146,148,149,150,163],[66,131,134,139,143,146,148,149,150,163,182],[66,131,135,136,139,143,146,148,149,150,154,163],[66,131,136,139,143,146,148,149,150,163,168,178],[66,131,137,139,142,143,146,148,149,150,152,163],[66,130,131,138,139,143,146,148,149,150,163],[66,131,139,140,143,146,148,149,150,163],[66,131,139,141,142,143,146,148,149,150,163],[66,130,131,139,142,143,146,148,149,150,163],[66,131,139,142,143,144,146,148,149,150,163,168,181],[66,131,139,142,143,144,146,148,149,150,163,168,170,172],[66,131,139,143,146,148,149,150,163],[66,118,131,139,142,143,145,146,148,149,150,152,163,168,181],[66,131,139,142,143,145,146,148,149,150,152,163,168,178,181],[66,131,139,143,145,146,147,148,149,150,163,168,178,181],[65,66,67,68,69,70,71,72,73,74,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189],[66,131,139,142,143,146,148,149,150,163],[66,131,139,143,146,148,150,163],[66,131,139,143,146,148,149,150,151,163,181],[66,131,139,142,143,146,148,149,150,152,163,168],[66,131,139,143,146,148,149,150,154,163],[66,131,139,143,146,148,149,150,155,163],[66,131,139,142,143,146,148,149,150,158,163],[66,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188],[66,131,139,143,146,148,149,150,160,163],[66,131,139,143,146,148,149,150,161,163],[66,131,136,139,143,146,148,149,150,152,163,172],[66,131,139,142,143,146,148,149,150,163,164],[66,131,139,143,146,148,149,150,163,165,182,185],[66,131,139,142,143,146,148,149,150,163,168,171,172],[66,131,139,143,146,148,149,150,163,169,172],[66,131,139,143,146,148,149,150,163,170],[66,131,139,143,146,148,149,150,163,172,182],[66,131,139,143,146,148,149,150,163,173],[66,128,131,139,143,146,148,149,150,163,168,175,181],[66,131,139,143,146,148,149,150,163,168,174],[66,131,139,142,143,146,148,149,150,163,176,177],[66,131,139,143,146,148,149,150,163,176,177],[66,131,136,139,143,146,148,149,150,152,163,168,178],[66,131,139,143,146,148,149,150,163,179],[66,131,139,143,146,148,149,150,152,163,180],[66,131,139,143,145,146,148,149,150,161,163,181],[66,131,139,143,146,148,149,150,163,182,183],[66,131,136,139,143,146,148,149,150,163,183],[66,131,139,143,146,148,149,150,163,168,184],[66,131,139,143,146,148,149,150,151,163,185],[66,131,139,143,146,148,149,150,163,186],[66,131,134,139,143,146,148,149,150,163],[66,131,136,139,143,146,148,149,150,163],[66,131,139,143,146,148,149,150,163,182],[66,118,131,139,143,146,148,149,150,163],[66,131,139,143,146,148,149,150,163,181],[66,131,139,143,146,148,149,150,163,187],[66,131,139,143,146,148,149,150,158,163],[66,131,139,143,146,148,149,150,163,177],[66,118,131,139,142,143,144,146,148,149,150,158,163,168,172,181,184,185,187],[66,131,139,143,146,148,149,150,163,168,188],[66,131,139,143,146,148,149,150,163,170,189],[66,81,84,87,88,131,139,143,146,148,149,150,163,181],[66,84,131,139,143,146,148,149,150,163,168,181],[66,84,88,131,139,143,146,148,149,150,163,181],[66,131,139,143,146,148,149,150,163,168],[66,78,131,139,143,146,148,149,150,163],[66,82,131,139,143,146,148,149,150,163],[66,80,81,84,131,139,143,146,148,149,150,163,181],[66,131,139,143,146,148,149,150,152,163,178],[66,131,139,143,146,148,149,150,163,190],[66,78,131,139,143,146,148,149,150,163,190],[66,80,84,131,139,143,146,148,149,150,152,163,181],[66,75,76,77,79,83,131,139,142,143,146,148,149,150,163,168,181],[66,84,131,139,143,146,148,149,150,163],[66,84,93,102,131,139,143,146,148,149,150,163],[66,76,82,131,139,143,146,148,149,150,163],[66,84,112,113,131,139,143,146,148,149,150,163],[66,76,79,84,131,139,143,146,148,149,150,163,172,181,190],[66,80,84,131,139,143,146,148,149,150,163,181],[66,75,131,139,143,146,148,149,150,163],[66,78,79,80,82,83,84,85,86,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,113,114,115,116,117,131,139,143,146,148,149,150,163],[66,84,105,108,131,139,143,146,148,149,150,163],[66,84,93,95,96,131,139,143,146,148,149,150,163],[66,82,84,95,97,131,139,143,146,148,149,150,163],[66,83,131,139,143,146,148,149,150,163],[66,76,78,84,131,139,143,146,148,149,150,163],[66,84,88,95,97,131,139,143,146,148,149,150,163],[66,88,131,139,143,146,148,149,150,163],[66,82,84,87,131,139,143,146,148,149,150,163,181],[66,76,80,84,93,131,139,143,146,148,149,150,163],[66,84,105,131,139,143,146,148,149,150,163],[66,97,131,139,143,146,148,149,150,163],[66,76,80,84,88,131,139,143,146,148,149,150,163],[66,78,84,112,131,139,143,146,148,149,150,163,172,187,190],[54,55,56,57,58,59,60,66,131,139,143,146,148,149,150,163],[55,66,131,139,143,146,148,149,150,163],[61,62,63,66,131,139,143,146,148,149,150,163]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"2a2de5b9459b3fc44decd9ce6100b72f1b002ef523126c1d3d8b2a4a63d74d78","affectsGlobalScope":true,"impliedFormat":1},{"version":"f13f4b465c99041e912db5c44129a94588e1aafee35a50eab51044833f50b4ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"f128dae7c44d8f35ee42e0a437000a57c9f06cc04f8b4fb42eebf44954d53dc8","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ecb8e347cb6b2a8927c09b86263663289418df375f5e68e11a0ae683776978f","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"577cc49be1979782a5a695b46049566d123e2a75382f10bb82f2e5c87e29059a","impliedFormat":1},{"version":"b075ac9e90ed56a547596133335f926eda887267c471aa7e45d33c70382288ba","signature":"0330df7dca26639378488e3f07620c171e4ff492d09827bbd563791eb0cce285"},{"version":"bec3f9f2832e7677f251adfe6166b1b5f95b68b1d8a6a15e5fdd868e0a8d3985","signature":"d12d4ca1595f15888fc8a020398cabb5bd67c609285acfa366824dcf9c7afeb6"},{"version":"e745f04102e3ca5bf615b67ddc6cf8bb12a8903f0015af761c9121dd9cbd02b2","signature":"9a804703f424101ebc20d4bd1f30644a4b29efff8a6d838fe5b86862f55546b9"},{"version":"0e723f9e09c4b005542d64e3e6e0cb88624c3030d7a300174c86850e869a197d","signature":"975cc26455dc6404a8758e1dd34dc243f189811ee0cc06fe684112d91bb063f5"},{"version":"dac2b370fe169b97095babcaa6a73ef55c092842551a8e8f3dbad80173ebe5e7","signature":"f249a786f0cec417b5a684f1b45d977f20c4cf631e6041954d179dfa3eda1b7a"},{"version":"06dee099219c62478f223a027377182dc87bc84f47f06733ebb1b2c8e4db33c3","signature":"ab144048351c9524803944ea38b3cff8d527168e2ef1c8307f8d26e0b875e75e"},{"version":"56233a437a5dca351fd9b3b04746cdf293ca7b71f5d3f53f7f15f61f33d889d1","signature":"3fb1ea5aa7aa1818a81ef0c986457cfc5c1d68ddb3bb1444de47ee77cec753cd"},{"version":"c3eb62064de4ead702608a306960c9096b16a1a71fec78a1314ba166b6aa87a9","signature":"57be780689ea085d80b1a8236466dfda1e433b09d36b9808e8690c588c4778aa"},{"version":"8519d14ca8f3ec519671bbd1966b092fb5edda0ee218749c4584ac975437b230","signature":"6ba52c4bbac233fec69f0f02bb1844ec3d54028e84e3d4205625521671f9d173"},{"version":"f9f416cbbe4b9eaa6ddc8d361ccb6895648b823ab58687fba9ae6faa492a250e","signature":"7ec90ed444c3b3ba04d9fc3c50d15513e03a807c7cda11487099b1cc3589af4a"},{"version":"d40a83ea0957264f5090b05a05fe68104b53f0ae5deb15882a27e4a57fd6f150","signature":"3c099f5a3656125c43d587278a5bcfcadb38619c7f848c4c0e20739c273787fb"},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"f53a7652392cf26ebbe4e29fd0672aa87c93bd6d0241289c13fab87b9ac35c8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"b00a630557d1622ad312633bdbfbdb9c6b7220d948dca9f899db30679f160074","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"88809d6c1b9c78d04a133646a6feb926def05a8774c308c7c93bc32ee163d271","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"3ac40516c33b87f751f7507346933081a26cdb8a3e11a6b3aa07d23f803c85db","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"829bc57ee8f287b490ab5bbc5a962fca57e432c1e38ec680ecd3ecaf12800613","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"3a3ff14da53d5013f3e6d8c4ad55225e3649c08786c4421ce639c00d8d589b7d","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"38004e6801340cb890afb8cb5a9fc8972297e7f88ab94026e4b0b3c61fb32f8a","impliedFormat":1},{"version":"d243db6b25788f439e7e2f03c05688e92f46764351673bb0e7b2f3631232e186","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"149f9a9e7f04e67afa0e2a49fc0ff421035c01d6b793cfcae7d2e9f6819431e2","impliedFormat":1},{"version":"e8a9dfa4c75ef6d25df8b40eaa9c31e0a69452aaf2ced4a3f4215dbdbaa876f4","impliedFormat":1},{"version":"a70af845a2eb9dd6e2723e319e14ea7fb28b129ec1361c21509b49305448c323","impliedFormat":1},{"version":"b53dc572d4f187904207ae1166652de47aab8eeb00c254d009cb226863076b56","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"f501234c5aeeeb5d7659412335227466aaacf30b952372d60afeb21c02c96348","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"9ac977503f15bf13ca7c82ad9a32a782f42d43e474824e8b3bffe228fd5f2639","impliedFormat":1},{"version":"8b91ff5bb912be3ea213cbcf0075aace1f5d4ff249a0d227ed673868cb7bfabc","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"7cb4f431a4591b0e23002bed805dc871a874dfed6b9a3994dce68a6df73e6739","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"e99963ae1e3a48ca7a7958c02f3e88bb963eb7978c28b68ae6b8c9f03309d83c","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"594ae90cacd813fa392ff80d2e0a8eff4e41f4a136329a940e321399dd8895b4","impliedFormat":1},{"version":"d1f333ade8ff35a409b4984e1f11956fe11c61855b0c7e9b59f0313e48b40c4a","impliedFormat":1},{"version":"0224aa4b3464895d69c413a640a19ac2166778a74eb5eb3b36b021c72d42b274","impliedFormat":1},{"version":"0828724f6c17d63075bc7bfdd2f22875c4d00f90a6d8ef16d2e718a9e5f7e135","affectsGlobalScope":true,"impliedFormat":1},{"version":"177459cba484e2f1e08872a3d2fdbca3162d9d43ca5ec9dc0c946835b55f74be","impliedFormat":1},{"version":"2fbf504c4791f9d32cd766cfe6b605bcda63289b925401953a7900db9af85348","impliedFormat":1},{"version":"ed0fb633cae35948d9e144004299a4bdf1ab912667c787b7fbffcd6d8c7b92a2","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"637e244cbc5174cce5482388be2b4b51c49f7ce6dead7316448da61d7aa283b1","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"afa8be176b15487addede2f996c733e8d33a23497e6efe01c3945f768cf79184","impliedFormat":1},{"version":"6a0de93048a43c4f492e1fe43cc4ec52eed57d4e03a07c78b2d502e20dbdcfd8","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"8c7e618c2a91ea7f6b5cca272a295864e92c16413be8fc56a943e8c7d5320011","affectsGlobalScope":true,"impliedFormat":1},{"version":"66e5d81f637da29b03689fbc84cc61f18c6fdde769b134e0649259384df453e2","impliedFormat":1},{"version":"f2bb6c145c2112b33fa26e7464c9c69212fd3fc163ee389230c22db39408ad1e","impliedFormat":1},{"version":"b02c915a1b0d9777a17e3249674735eec3f2fd929f0d63da84157aac7f9a4345","impliedFormat":1},{"version":"62e8f884c3bc6dff6189b6e662ebe8b238a645938f2df7a97b8a82fca56773a4","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"57a0d1b3d59063d4af2d3f8aac27cfe3c20a0f5d1faf0f8598ccf0b779637939","impliedFormat":1},{"version":"5ff4433a2deae4f85ab1377e90a7554ce6b47ae51c69a84ca30a6e22fae85834","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"97234c5303866576f913d0ccae7d58d6322d9e803c7bf1228a3fda46ab8087b2","affectsGlobalScope":true,"impliedFormat":1},{"version":"93ecf87143cac7b9d05cffc1d6bdc075b7e4fdd48ff05f1fad85043f6ae678d3","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"6f200afcb82b3e9a54bed6db23f2edf2508cd266801257312c0f124b47f2bdb9","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"39338f84e8c4d0e3de7b3c4a7024fb3925f42100eed5cbe73be58902799dff4d","impliedFormat":1},{"version":"f1c92c0b24d678486042dfc038c7c1d6e8520fe384b82155720a42a893204588","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"8413d0641f293aed551c7464615b770d34a02dedede889b9591172287d68e773","impliedFormat":1},{"version":"441b9bb09013654aa3d050e68b06464d8959b473e85868249d9d18f692acd35b","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"55246f15e33ff1e2e9e679b25fa9790a48db55dc63d567fe25fac8b6a0efe911","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"8bb351077998efc2d986a6a7373cba6f098a91a3679cefce3ba2aab90493161c","impliedFormat":1},{"version":"734665cf52eb63e20252412ca891601b1405f7c6abef6425f1939cbb15ed239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"f36b3fbe2be150a9ca140da48593f21e6a8172004f92ddc549b43efec39f3e54","impliedFormat":1},{"version":"f12624a4a8d042b68914eac1b0a16571fc1c523173fcdf2517c65d191bd5a86c","impliedFormat":1},{"version":"b4769767f13a1692a66186e01c3aa186ff808d5ff72ed36eda8c37738fb2ac92","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"ae6adca0538007af480cf43e20b1e7631c5321406bc515bff980a0d31252f79f","impliedFormat":1},{"version":"1ec3f3a5f04cc42df33274fbe5c0937d9a9e06f249a7a26288d7d54f0763ffd4","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"e47f532d6e1617833f13a5b0710c0089d402c89c2f2b54f324e5a20e418d287a","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"8e2577e7262051fd3c5bd6ca2b2056d358ff8853565720f92455860824c25188","impliedFormat":1},{"version":"5cbb49cb13edc05e52b239329932cfde34323c6bfe33020e381faa97d2300b22","impliedFormat":1},{"version":"bb9dbb4b2ad81e3e71ec5ba4314973718555b9d04ba2a17dfbf875efecb8e2c0","impliedFormat":1},{"version":"62e02b8bbc05076243cf153d10c27b3d886c7c08558dfb797f280d837881b3cd","impliedFormat":1},{"version":"045a210189ec63c5488410b33f9fca53d77d051599d0d6506d8048551399c5f3","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"3ead5b9bea1c59a375acdd494ac503f6e16a2b47cffbc31da1824fc17d023205","impliedFormat":1},{"version":"c9a2daf6cd1eb854cd5b9e424247c5e306692055738c2effd35f7871d942b76e","impliedFormat":1},{"version":"afa1c49f8e559e413d57343339db857d2a8159435cf9cf7d4deb41718fff1b88","impliedFormat":1},{"version":"e423ccd43347320b61eea979368bd0e80785c0823995b4f46ec3c9b4dadcd45f","impliedFormat":1}],"root":[[54,64]],"options":{"composite":true,"declaration":true,"esModuleInterop":true,"module":1,"outDir":"./","preserveConstEnums":true,"removeComments":false,"rootDir":"../src","skipLibCheck":true,"strict":true,"target":7,"tsBuildInfoFile":"./.tsbuildinfo"},"referencedMap":[[128,1],[129,1],[130,2],[66,3],[131,4],[132,5],[133,6],[134,7],[135,8],[136,9],[137,10],[138,11],[139,12],[140,12],[141,13],[142,14],[143,15],[144,16],[67,17],[65,17],[145,18],[146,19],[147,20],[190,21],[148,22],[149,23],[150,22],[151,24],[152,25],[154,26],[155,27],[156,27],[157,27],[158,28],[159,29],[160,30],[161,31],[162,32],[163,33],[164,33],[165,34],[166,17],[167,17],[168,35],[169,36],[170,37],[171,35],[172,38],[173,39],[174,40],[175,41],[176,42],[177,43],[178,44],[179,45],[180,46],[181,47],[182,48],[183,49],[184,50],[185,51],[186,52],[68,22],[69,17],[70,53],[71,54],[72,17],[73,55],[74,17],[119,56],[120,57],[121,58],[122,58],[123,59],[124,17],[125,4],[126,60],[127,57],[187,61],[188,62],[189,63],[153,17],[51,17],[52,17],[10,17],[8,17],[9,17],[14,17],[13,17],[2,17],[15,17],[16,17],[17,17],[18,17],[19,17],[20,17],[21,17],[22,17],[3,17],[23,17],[24,17],[4,17],[25,17],[29,17],[26,17],[27,17],[28,17],[30,17],[31,17],[32,17],[5,17],[33,17],[34,17],[35,17],[36,17],[6,17],[40,17],[37,17],[38,17],[39,17],[41,17],[7,17],[42,17],[53,17],[47,17],[48,17],[43,17],[44,17],[45,17],[46,17],[49,17],[1,17],[50,17],[12,17],[11,17],[93,64],[107,65],[90,66],[108,67],[117,68],[81,69],[82,70],[80,71],[116,72],[111,73],[115,74],[84,75],[94,76],[104,77],[83,78],[114,79],[78,80],[79,73],[85,76],[86,17],[92,81],[89,76],[76,82],[118,83],[109,84],[97,85],[96,76],[98,86],[101,87],[95,88],[99,89],[112,72],[87,90],[88,91],[102,92],[77,67],[106,93],[105,76],[91,91],[100,94],[103,95],[110,17],[75,17],[113,96],[61,97],[60,98],[64,99],[63,17],[54,17],[55,17],[56,17],[57,17],[58,17],[59,17],[62,17]],"latestChangedDtsFile":"./index.d.ts","version":"6.0.3"}
@@ -75,5 +75,7 @@ function getBoardCodes(board) {
75
75
  function stringifyCardCode(code) {
76
76
  const rank = code >> 2;
77
77
  const suit = code & 0b11;
78
- return (RANK_CHARS[rank] || "?") + (SUIT_CHARS[suit] || "?");
78
+ const rankChar = RANK_CHARS[rank] || "?";
79
+ const suitChar = SUIT_CHARS[suit] || "?";
80
+ return rankChar + suitChar;
79
81
  }
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "@pokertools/evaluator",
3
- "version": "1.0.1",
3
+ "version": "1.0.6",
4
4
  "description": "High-performance Poker Hand Evaluator (5, 6, and 7 cards)",
5
+ "author": "A.Aurelius",
6
+ "license": "MIT",
5
7
  "main": "dist/index.js",
6
8
  "types": "dist/index.d.ts",
7
9
  "exports": {
@@ -17,9 +19,17 @@
17
19
  "README.md",
18
20
  "LICENSE"
19
21
  ],
22
+ "sideEffects": false,
20
23
  "scripts": {
21
24
  "build": "tsc",
22
- "test": "NODE_OPTIONS='--no-warnings' jest"
25
+ "build:watch": "tsc --watch",
26
+ "clean": "rm -rf dist coverage",
27
+ "typecheck": "tsc --noEmit",
28
+ "lint": "eslint . --ext .ts",
29
+ "lint:fix": "eslint . --ext .ts --fix",
30
+ "test": "NODE_OPTIONS='--no-warnings' jest",
31
+ "test:watch": "NODE_OPTIONS='--no-warnings' jest --watch",
32
+ "test:coverage": "NODE_OPTIONS='--no-warnings' jest --coverage"
23
33
  },
24
34
  "keywords": [
25
35
  "poker",
@@ -31,10 +41,10 @@
31
41
  "poker-hand",
32
42
  "poker-evaluator",
33
43
  "card-game",
34
- "performance"
44
+ "performance",
45
+ "fast",
46
+ "algorithm"
35
47
  ],
36
- "author": "A.Aurelius",
37
- "license": "MIT",
38
48
  "repository": {
39
49
  "type": "git",
40
50
  "url": "https://github.com/aaurelions/pokertools.git",
@@ -46,5 +56,8 @@
46
56
  },
47
57
  "publishConfig": {
48
58
  "access": "public"
59
+ },
60
+ "engines": {
61
+ "node": ">=18.0.0"
49
62
  }
50
63
  }
@@ -1 +0,0 @@
1
- {"root":["../src/index.ts","../src/core/evaluator.ts","../src/core/hash.ts","../src/models/hand-rank.ts","../src/tables/bit-masks.ts","../src/tables/dp.ts","../src/tables/flush.ts","../src/tables/no-flush-5.ts","../src/tables/no-flush-6.ts","../src/tables/no-flush-7.ts","../src/utils/card.ts"],"version":"5.9.3"}