@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 +535 -87
- package/dist/.tsbuildinfo +1 -0
- package/dist/utils/card.js +3 -1
- package/package.json +18 -5
- package/dist/tsconfig.tsbuildinfo +0 -1
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
|
[](https://www.npmjs.com/package/@pokertools/evaluator)
|
|
4
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
5
8
|
|
|
6
|
-
A
|
|
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
|
-
|
|
11
|
+
---
|
|
9
12
|
|
|
10
|
-
##
|
|
13
|
+
## ⚡ Performance
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
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
|
-
|
|
29
|
+
---
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
## 📦 Installation
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
37
|
+
```bash
|
|
38
|
+
yarn add @pokertools/evaluator
|
|
39
|
+
```
|
|
30
40
|
|
|
31
|
-
```
|
|
32
|
-
|
|
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
|
-
|
|
45
|
+
---
|
|
43
46
|
|
|
44
|
-
##
|
|
47
|
+
## 🚀 Quick Start
|
|
45
48
|
|
|
46
|
-
```
|
|
47
|
-
|
|
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
|
-
|
|
99
|
+
---
|
|
51
100
|
|
|
52
|
-
|
|
101
|
+
#### `evaluateStrings(cards: string[]): number`
|
|
53
102
|
|
|
54
|
-
|
|
103
|
+
Evaluates an array of card strings. Convenient but slightly slower than `evaluate()` due to parsing overhead.
|
|
55
104
|
|
|
56
105
|
```typescript
|
|
57
|
-
import {
|
|
106
|
+
import { evaluateStrings } from "@pokertools/evaluator";
|
|
107
|
+
|
|
108
|
+
// 5-card hand
|
|
109
|
+
const score5 = evaluateStrings(["As", "Ks", "Qs", "Js", "Ts"]);
|
|
58
110
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
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
|
-
//
|
|
64
|
-
const
|
|
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
|
-
|
|
118
|
+
---
|
|
69
119
|
|
|
70
|
-
|
|
120
|
+
#### `evaluateBoard(board: string): number`
|
|
121
|
+
|
|
122
|
+
Evaluates a space-separated board string.
|
|
71
123
|
|
|
72
124
|
```typescript
|
|
73
|
-
import {
|
|
125
|
+
import { evaluateBoard } from "@pokertools/evaluator";
|
|
74
126
|
|
|
75
|
-
//
|
|
76
|
-
const
|
|
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
|
-
//
|
|
80
|
-
const
|
|
130
|
+
// Just the board (5 community cards)
|
|
131
|
+
const boardScore = evaluateBoard("As Ks Qs Js Ts");
|
|
81
132
|
|
|
82
|
-
//
|
|
83
|
-
const
|
|
133
|
+
// Extra whitespace is handled
|
|
134
|
+
const score2 = evaluateBoard("As Ks Qs Js Ts");
|
|
135
|
+
```
|
|
84
136
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
|
|
152
|
+
---
|
|
92
153
|
|
|
93
|
-
|
|
154
|
+
#### `rankBoard(board: string): HandRank`
|
|
94
155
|
|
|
95
|
-
|
|
156
|
+
Returns the hand rank category for a board string.
|
|
96
157
|
|
|
97
|
-
|
|
158
|
+
```typescript
|
|
159
|
+
import { rankBoard, HandRank } from "@pokertools/evaluator";
|
|
98
160
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
161
|
+
const handRank = rankBoard("As Ks Qs Js Ts");
|
|
162
|
+
console.log(handRank === HandRank.StraightFlush); // true
|
|
163
|
+
```
|
|
102
164
|
|
|
103
|
-
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
#### `rankDescription(rank: HandRank): string`
|
|
104
168
|
|
|
105
|
-
|
|
169
|
+
Returns the human-readable name of a hand rank.
|
|
106
170
|
|
|
107
|
-
|
|
171
|
+
```typescript
|
|
172
|
+
import { rankBoard, rankDescription } from "@pokertools/evaluator";
|
|
108
173
|
|
|
109
|
-
|
|
174
|
+
const handRank = rankBoard("As Ah Ad Kh Kd");
|
|
175
|
+
const name = rankDescription(handRank);
|
|
176
|
+
console.log(name); // "Full House"
|
|
177
|
+
```
|
|
110
178
|
|
|
111
|
-
|
|
179
|
+
---
|
|
112
180
|
|
|
113
|
-
|
|
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
|
-
|
|
212
|
+
#### `getCardCodes(cards: string[]): number[]`
|
|
116
213
|
|
|
117
|
-
|
|
214
|
+
Converts an array of card strings to integer codes.
|
|
118
215
|
|
|
119
216
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
468
|
+
```
|
|
469
|
+
Card Integer = (RankIndex << 2) | SuitIndex
|
|
140
470
|
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
|
|
593
|
+
## 📄 License
|
|
146
594
|
|
|
147
|
-
|
|
595
|
+
MIT © A.Aurelius
|
|
148
596
|
|
|
149
|
-
|
|
597
|
+
---
|
|
150
598
|
|
|
151
|
-
|
|
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
|
-
|
|
601
|
+
Algorithm based on the perfect hash technique pioneered by:
|
|
156
602
|
|
|
157
|
-
|
|
603
|
+
- Cactus Kev's Poker Hand Evaluator
|
|
604
|
+
- Two Plus Two evaluator
|
|
605
|
+
- Senzee's 5-card evaluator
|
|
158
606
|
|
|
159
|
-
|
|
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"}
|
package/dist/utils/card.js
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
"
|
|
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"}
|