shufflecom-calculations 3.0.4 → 3.1.0
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/lib/games/baccarat.d.ts +54 -0
- package/lib/games/baccarat.js +224 -0
- package/lib/games/baccarat.js.map +1 -0
- package/lib/games/gameCalculation.d.ts +0 -6
- package/lib/games/gameCalculation.js +0 -9
- package/lib/games/gameCalculation.js.map +1 -1
- package/lib/index.d.ts +5 -0
- package/lib/index.js +19 -1
- package/lib/index.js.map +1 -1
- package/lib/regex/index.js +1 -1
- package/lib/regex/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/games/baccarat.spec.ts +805 -0
- package/src/games/baccarat.ts +273 -0
- package/src/games/chicken.spec.ts +5 -6
- package/src/games/gameCalculation.ts +0 -25
- package/src/index.ts +5 -0
- package/src/regex/index.ts +2 -2
- package/src/regex/regex.spec.ts +15 -6
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
import { createHmac } from 'crypto';
|
|
2
|
+
import BigNumber from 'bignumber.js';
|
|
3
|
+
import { CardGames, CardValue, Suits } from './cardGames';
|
|
4
|
+
import { Baccarat, BaccaratBet, BaccaratBetType, BaccaratGameResult, BaccaratOutcome } from './baccarat';
|
|
5
|
+
|
|
6
|
+
const ci = (value: CardValue, suit: Suits): number => CardGames.getCardIndexFromDetails({ value, suit });
|
|
7
|
+
|
|
8
|
+
const hexString = (serverSeed: string, clientSeed: string, nonce: string): string => {
|
|
9
|
+
const hmac = createHmac('sha256', serverSeed);
|
|
10
|
+
hmac.update(`${clientSeed}:${nonce}:0`);
|
|
11
|
+
return hmac.digest('hex');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const mockResult = (
|
|
15
|
+
playerCards: number[],
|
|
16
|
+
bankerCards: number[],
|
|
17
|
+
playerHandValue: number,
|
|
18
|
+
bankerHandValue: number,
|
|
19
|
+
outcome: BaccaratOutcome,
|
|
20
|
+
): BaccaratGameResult => ({ playerCards, bankerCards, playerHandValue, bankerHandValue, outcome });
|
|
21
|
+
|
|
22
|
+
const bet = (type: BaccaratBetType, amount: number): BaccaratBet => ({ type, amount: new BigNumber(amount) });
|
|
23
|
+
|
|
24
|
+
const SEED1 = {
|
|
25
|
+
serverSeed: 'ebd3ff712ee7ed3cabe3753146f95847b017f847758ed254c531ff0d45686cea',
|
|
26
|
+
clientSeed: 'pf4jl5q97q',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const SEED2 = {
|
|
30
|
+
serverSeed: '652fb02cbce322c4232a9032d905ca580c77ed9cf4850ba6ce9990527d37949f',
|
|
31
|
+
clientSeed: 'l5sgv5cutr',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
describe('Baccarat', () => {
|
|
35
|
+
describe('getBaccaratCardValue', () => {
|
|
36
|
+
it('returns face value for 2–9', () => {
|
|
37
|
+
expect(Baccarat.getBaccaratCardValue(0)).toBe(2);
|
|
38
|
+
expect(Baccarat.getBaccaratCardValue(28)).toBe(9);
|
|
39
|
+
expect(Baccarat.getBaccaratCardValue(20)).toBe(7);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('returns 0 for 10, J, Q, K', () => {
|
|
43
|
+
expect(Baccarat.getBaccaratCardValue(32)).toBe(0);
|
|
44
|
+
expect(Baccarat.getBaccaratCardValue(37)).toBe(0);
|
|
45
|
+
expect(Baccarat.getBaccaratCardValue(42)).toBe(0);
|
|
46
|
+
expect(Baccarat.getBaccaratCardValue(47)).toBe(0);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('returns 1 for Ace', () => {
|
|
50
|
+
expect(Baccarat.getBaccaratCardValue(48)).toBe(1);
|
|
51
|
+
expect(Baccarat.getBaccaratCardValue(51)).toBe(1);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('calcHandValue', () => {
|
|
56
|
+
it('returns sum of card values mod 10', () => {
|
|
57
|
+
expect(Baccarat.calcHandValue([0, 28])).toBe(1);
|
|
58
|
+
expect(Baccarat.calcHandValue([25, 49])).toBe(9);
|
|
59
|
+
expect(Baccarat.calcHandValue([20, 35])).toBe(7);
|
|
60
|
+
expect(Baccarat.calcHandValue([36, 44])).toBe(0);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('handles three-card hands correctly', () => {
|
|
64
|
+
expect(Baccarat.calcHandValue([0, 28, 45])).toBe(1);
|
|
65
|
+
expect(Baccarat.calcHandValue([14, 39, 3])).toBe(7);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('isNatural', () => {
|
|
70
|
+
it('returns true only for 8 and 9', () => {
|
|
71
|
+
expect(Baccarat.isNatural(8, [ci('8', Suits.CLUBS), ci('K', Suits.HEARTS)])).toBe(true);
|
|
72
|
+
expect(Baccarat.isNatural(9, [ci('9', Suits.CLUBS), ci('K', Suits.HEARTS)])).toBe(true);
|
|
73
|
+
expect(Baccarat.isNatural(7, [ci('7', Suits.CLUBS), ci('K', Suits.HEARTS)])).toBe(false);
|
|
74
|
+
expect(Baccarat.isNatural(0, [ci('2', Suits.CLUBS), ci('K', Suits.HEARTS)])).toBe(false);
|
|
75
|
+
expect(Baccarat.isNatural(8, [ci('2', Suits.CLUBS), ci('10', Suits.HEARTS), ci('6', Suits.DIAMONDS)])).toBe(false);
|
|
76
|
+
expect(Baccarat.isNatural(9, [ci('3', Suits.CLUBS), ci('5', Suits.HEARTS), ci('A', Suits.DIAMONDS)])).toBe(false);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('hasPair', () => {
|
|
81
|
+
it('returns true when first two cards share the same rank', () => {
|
|
82
|
+
expect(Baccarat.hasPair([ci('7', Suits.CLUBS), ci('7', Suits.HEARTS)])).toBe(true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('returns true for a perfect pair (identical cards)', () => {
|
|
86
|
+
expect(Baccarat.hasPair([ci('7', Suits.CLUBS), ci('7', Suits.CLUBS)])).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('returns false when ranks differ', () => {
|
|
90
|
+
expect(Baccarat.hasPair([ci('7', Suits.CLUBS), ci('8', Suits.CLUBS)])).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('hasPerfectPair', () => {
|
|
95
|
+
it('returns true only when both cards are the exact same index', () => {
|
|
96
|
+
const card = ci('7', Suits.CLUBS);
|
|
97
|
+
expect(Baccarat.hasPerfectPair([card, card])).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('returns false when ranks match but suits differ', () => {
|
|
101
|
+
expect(Baccarat.hasPerfectPair([ci('7', Suits.CLUBS), ci('7', Suits.HEARTS)])).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('getGameResult', () => {
|
|
106
|
+
it('banker wins — player draws third, banker does not (nonce 2, SEED1)', () => {
|
|
107
|
+
const result = Baccarat.getGameResult(hexString(SEED1.serverSeed, SEED1.clientSeed, '2'));
|
|
108
|
+
expect(result.playerHandValue).toBe(2);
|
|
109
|
+
expect(result.playerCards).toHaveLength(3);
|
|
110
|
+
expect(result.bankerHandValue).toBe(6);
|
|
111
|
+
expect(result.bankerCards).toHaveLength(2);
|
|
112
|
+
expect(result.outcome).toBe(BaccaratOutcome.BANKER_WIN);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('player wins — both hands draw third card (nonce 3, SEED1)', () => {
|
|
116
|
+
const result = Baccarat.getGameResult(hexString(SEED1.serverSeed, SEED1.clientSeed, '3'));
|
|
117
|
+
expect(result.playerHandValue).toBe(4);
|
|
118
|
+
expect(result.playerCards).toHaveLength(3);
|
|
119
|
+
expect(result.bankerHandValue).toBe(1);
|
|
120
|
+
expect(result.bankerCards).toHaveLength(3);
|
|
121
|
+
expect(result.outcome).toBe(BaccaratOutcome.PLAYER_WIN);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('player wins — both hands draw third card (nonce 4, SEED1)', () => {
|
|
125
|
+
const result = Baccarat.getGameResult(hexString(SEED1.serverSeed, SEED1.clientSeed, '4'));
|
|
126
|
+
expect(result.playerHandValue).toBe(5);
|
|
127
|
+
expect(result.playerCards).toHaveLength(3);
|
|
128
|
+
expect(result.bankerHandValue).toBe(4);
|
|
129
|
+
expect(result.bankerCards).toHaveLength(3);
|
|
130
|
+
expect(result.outcome).toBe(BaccaratOutcome.PLAYER_WIN);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('player wins — player stands, banker draws third (nonce 2476, SEED2)', () => {
|
|
134
|
+
const result = Baccarat.getGameResult(hexString(SEED2.serverSeed, SEED2.clientSeed, '2476'));
|
|
135
|
+
expect(result.playerHandValue).toBe(7);
|
|
136
|
+
expect(result.playerCards).toHaveLength(2);
|
|
137
|
+
expect(result.bankerHandValue).toBe(4);
|
|
138
|
+
expect(result.bankerCards).toHaveLength(3);
|
|
139
|
+
expect(result.outcome).toBe(BaccaratOutcome.PLAYER_WIN);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('calcBetPayouts', () => {
|
|
144
|
+
describe('main bets', () => {
|
|
145
|
+
it('player wins 1:1', () => {
|
|
146
|
+
const result = mockResult(
|
|
147
|
+
[ci('6', Suits.CLUBS), ci('3', Suits.CLUBS)],
|
|
148
|
+
[ci('2', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
149
|
+
9,
|
|
150
|
+
5,
|
|
151
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
152
|
+
);
|
|
153
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER, 100)], result);
|
|
154
|
+
expect(payout.toNumber()).toBe(200);
|
|
155
|
+
expect(multiplier.toNumber()).toBe(2);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('banker wins with 0.95:1 commission', () => {
|
|
159
|
+
const result = mockResult(
|
|
160
|
+
[ci('3', Suits.CLUBS), ci('A', Suits.DIAMONDS)],
|
|
161
|
+
[ci('8', Suits.CLUBS), ci('Q', Suits.DIAMONDS)],
|
|
162
|
+
4,
|
|
163
|
+
8,
|
|
164
|
+
BaccaratOutcome.BANKER_WIN,
|
|
165
|
+
);
|
|
166
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER, 100)], result);
|
|
167
|
+
expect(payout.toNumber()).toBe(195);
|
|
168
|
+
expect(multiplier.toNumber()).toBe(1.95);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('player bet pushes on tie', () => {
|
|
172
|
+
const result = mockResult(
|
|
173
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
174
|
+
[ci('2', Suits.CLUBS), ci('4', Suits.DIAMONDS)],
|
|
175
|
+
6,
|
|
176
|
+
6,
|
|
177
|
+
BaccaratOutcome.TIE,
|
|
178
|
+
);
|
|
179
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER, 100)], result);
|
|
180
|
+
expect(payout.toNumber()).toBe(100);
|
|
181
|
+
expect(multiplier.toNumber()).toBe(1);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('banker bet pushes on tie', () => {
|
|
185
|
+
const result = mockResult(
|
|
186
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
187
|
+
[ci('4', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
188
|
+
6,
|
|
189
|
+
6,
|
|
190
|
+
BaccaratOutcome.TIE,
|
|
191
|
+
);
|
|
192
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER, 100)], result);
|
|
193
|
+
expect(payout.toNumber()).toBe(100);
|
|
194
|
+
expect(multiplier.toNumber()).toBe(1);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('losing bet returns 0', () => {
|
|
198
|
+
const result = mockResult(
|
|
199
|
+
[ci('3', Suits.CLUBS), ci('A', Suits.DIAMONDS)],
|
|
200
|
+
[ci('8', Suits.CLUBS), ci('Q', Suits.DIAMONDS)],
|
|
201
|
+
4,
|
|
202
|
+
8,
|
|
203
|
+
BaccaratOutcome.BANKER_WIN,
|
|
204
|
+
);
|
|
205
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER, 100)], result);
|
|
206
|
+
expect(payout.toNumber()).toBe(0);
|
|
207
|
+
expect(multiplier.toNumber()).toBe(0);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe('tie bet', () => {
|
|
212
|
+
it('tie pays 8:1', () => {
|
|
213
|
+
const result = mockResult(
|
|
214
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
215
|
+
[ci('2', Suits.CLUBS), ci('4', Suits.DIAMONDS)],
|
|
216
|
+
6,
|
|
217
|
+
6,
|
|
218
|
+
BaccaratOutcome.TIE,
|
|
219
|
+
);
|
|
220
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.TIE, 50)], result);
|
|
221
|
+
expect(payout.toNumber()).toBe(450);
|
|
222
|
+
expect(multiplier.toNumber()).toBe(9);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('tie bet loses when player wins', () => {
|
|
226
|
+
const result = mockResult(
|
|
227
|
+
[ci('6', Suits.CLUBS), ci('3', Suits.CLUBS)],
|
|
228
|
+
[ci('2', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
229
|
+
9,
|
|
230
|
+
5,
|
|
231
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
232
|
+
);
|
|
233
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.TIE, 50)], result);
|
|
234
|
+
expect(payout.toNumber()).toBe(0);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('tie bet loses when banker wins', () => {
|
|
238
|
+
const result = mockResult(
|
|
239
|
+
[ci('3', Suits.CLUBS), ci('A', Suits.DIAMONDS)],
|
|
240
|
+
[ci('8', Suits.CLUBS), ci('Q', Suits.DIAMONDS)],
|
|
241
|
+
4,
|
|
242
|
+
8,
|
|
243
|
+
BaccaratOutcome.BANKER_WIN,
|
|
244
|
+
);
|
|
245
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.TIE, 50)], result);
|
|
246
|
+
expect(payout.toNumber()).toBe(0);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
describe('pair side bets', () => {
|
|
251
|
+
it('P Pair pays 11:1 when player has a pair', () => {
|
|
252
|
+
const result = mockResult(
|
|
253
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
254
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
255
|
+
8,
|
|
256
|
+
5,
|
|
257
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
258
|
+
);
|
|
259
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_PAIR, 10)], result);
|
|
260
|
+
expect(payout.toNumber()).toBe(120);
|
|
261
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('P Pair pays 11:1 when player has a pair but banker wins', () => {
|
|
265
|
+
const result = mockResult(
|
|
266
|
+
[ci('7', Suits.CLUBS), ci('7', Suits.HEARTS), ci('2', Suits.DIAMONDS)],
|
|
267
|
+
[ci('3', Suits.DIAMONDS), ci('4', Suits.CLUBS)],
|
|
268
|
+
6,
|
|
269
|
+
7,
|
|
270
|
+
BaccaratOutcome.BANKER_WIN,
|
|
271
|
+
);
|
|
272
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_PAIR, 10)], result);
|
|
273
|
+
expect(payout.toNumber()).toBe(120);
|
|
274
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('P Pair loses when player has no pair', () => {
|
|
278
|
+
const result = mockResult(
|
|
279
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
280
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('3', Suits.HEARTS)],
|
|
281
|
+
7,
|
|
282
|
+
6,
|
|
283
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
284
|
+
);
|
|
285
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_PAIR, 10)], result);
|
|
286
|
+
expect(payout.toNumber()).toBe(0);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('P Pair loses when banker has a pair but player does not', () => {
|
|
290
|
+
const result = mockResult(
|
|
291
|
+
[ci('7', Suits.CLUBS), ci('9', Suits.CLUBS)],
|
|
292
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.HEARTS)],
|
|
293
|
+
6,
|
|
294
|
+
6,
|
|
295
|
+
BaccaratOutcome.TIE,
|
|
296
|
+
);
|
|
297
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_PAIR, 10)], result);
|
|
298
|
+
expect(payout.toNumber()).toBe(0);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('P Pair pays 11:1 when it is a tie', () => {
|
|
302
|
+
const result = mockResult(
|
|
303
|
+
[ci('7', Suits.CLUBS), ci('7', Suits.HEARTS), ci('2', Suits.DIAMONDS)],
|
|
304
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.HEARTS)],
|
|
305
|
+
6,
|
|
306
|
+
6,
|
|
307
|
+
BaccaratOutcome.TIE,
|
|
308
|
+
);
|
|
309
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_PAIR, 10)], result);
|
|
310
|
+
expect(payout.toNumber()).toBe(120);
|
|
311
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('B Pair pays 11:1 when banker has a pair', () => {
|
|
315
|
+
const result = mockResult(
|
|
316
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
317
|
+
[ci('9', Suits.DIAMONDS), ci('9', Suits.HEARTS)],
|
|
318
|
+
5,
|
|
319
|
+
8,
|
|
320
|
+
BaccaratOutcome.BANKER_WIN,
|
|
321
|
+
);
|
|
322
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_PAIR, 10)], result);
|
|
323
|
+
expect(payout.toNumber()).toBe(120);
|
|
324
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('B Pair pays 11:1 when banker has a pair but loses', () => {
|
|
328
|
+
const result = mockResult(
|
|
329
|
+
[ci('3', Suits.CLUBS), ci('4', Suits.DIAMONDS)],
|
|
330
|
+
[ci('6', Suits.DIAMONDS), ci('6', Suits.HEARTS), ci('10', Suits.CLUBS)],
|
|
331
|
+
7,
|
|
332
|
+
2,
|
|
333
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
334
|
+
);
|
|
335
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_PAIR, 10)], result);
|
|
336
|
+
expect(payout.toNumber()).toBe(120);
|
|
337
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('B Pair pays 11:1 when both banker and player have a pair', () => {
|
|
341
|
+
const result = mockResult(
|
|
342
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.HEARTS)],
|
|
343
|
+
[ci('6', Suits.DIAMONDS), ci('6', Suits.HEARTS), ci('10', Suits.CLUBS)],
|
|
344
|
+
6,
|
|
345
|
+
2,
|
|
346
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
347
|
+
);
|
|
348
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_PAIR, 10)], result);
|
|
349
|
+
expect(payout.toNumber()).toBe(120);
|
|
350
|
+
expect(multiplier.toNumber()).toBe(12);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('B Pair loses when player has a pair but banker does not', () => {
|
|
354
|
+
const result = mockResult(
|
|
355
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.HEARTS)],
|
|
356
|
+
[ci('10', Suits.DIAMONDS), ci('7', Suits.HEARTS)],
|
|
357
|
+
6,
|
|
358
|
+
7,
|
|
359
|
+
BaccaratOutcome.BANKER_WIN,
|
|
360
|
+
);
|
|
361
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_PAIR, 10)], result);
|
|
362
|
+
expect(payout.toNumber()).toBe(0);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('Either Pair pays 5:1 when player has a pair', () => {
|
|
366
|
+
const result = mockResult(
|
|
367
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
368
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
369
|
+
8,
|
|
370
|
+
5,
|
|
371
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
372
|
+
);
|
|
373
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.EITHER_PAIR, 10)], result);
|
|
374
|
+
expect(payout.toNumber()).toBe(60);
|
|
375
|
+
expect(multiplier.toNumber()).toBe(6);
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('Either Pair pays 5:1 when banker has a pair', () => {
|
|
379
|
+
const result = mockResult(
|
|
380
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
381
|
+
[ci('9', Suits.DIAMONDS), ci('9', Suits.HEARTS)],
|
|
382
|
+
5,
|
|
383
|
+
8,
|
|
384
|
+
BaccaratOutcome.BANKER_WIN,
|
|
385
|
+
);
|
|
386
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.EITHER_PAIR, 10)], result);
|
|
387
|
+
expect(payout.toNumber()).toBe(60);
|
|
388
|
+
expect(multiplier.toNumber()).toBe(6);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('Either Pair pays 5:1 when both hands have a pair', () => {
|
|
392
|
+
const result = mockResult(
|
|
393
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
394
|
+
[ci('9', Suits.DIAMONDS), ci('9', Suits.HEARTS)],
|
|
395
|
+
8,
|
|
396
|
+
8,
|
|
397
|
+
BaccaratOutcome.TIE,
|
|
398
|
+
);
|
|
399
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.EITHER_PAIR, 10)], result);
|
|
400
|
+
expect(payout.toNumber()).toBe(60);
|
|
401
|
+
expect(multiplier.toNumber()).toBe(6);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('Either Pair loses when neither hand has a pair', () => {
|
|
405
|
+
const result = mockResult(
|
|
406
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
407
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('3', Suits.HEARTS)],
|
|
408
|
+
7,
|
|
409
|
+
6,
|
|
410
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
411
|
+
);
|
|
412
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.EITHER_PAIR, 10)], result);
|
|
413
|
+
expect(payout.toNumber()).toBe(0);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
describe('perfect pair side bet', () => {
|
|
418
|
+
it('pays 25:1 when exactly one hand has a perfect pair', () => {
|
|
419
|
+
const card = ci('4', Suits.CLUBS);
|
|
420
|
+
const result = mockResult([card, card], [ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)], 8, 5, BaccaratOutcome.PLAYER_WIN);
|
|
421
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PERFECT_PAIR, 10)], result);
|
|
422
|
+
expect(payout.toNumber()).toBe(260);
|
|
423
|
+
expect(multiplier.toNumber()).toBe(26);
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('pays 25:1 when player has a non-perfect pair but banker has a non-perfect pair', () => {
|
|
427
|
+
const bankerCard = ci('4', Suits.CLUBS);
|
|
428
|
+
const result = mockResult([ci('K', Suits.HEARTS), ci('K', Suits.DIAMONDS)], [bankerCard, bankerCard], 0, 8, BaccaratOutcome.BANKER_WIN);
|
|
429
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PERFECT_PAIR, 10)], result);
|
|
430
|
+
expect(payout.toNumber()).toBe(260);
|
|
431
|
+
expect(multiplier.toNumber()).toBe(26);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it('pays 200:1 when both hands have a perfect pair', () => {
|
|
435
|
+
const playerCard = ci('4', Suits.CLUBS);
|
|
436
|
+
const bankerCard = ci('K', Suits.DIAMONDS);
|
|
437
|
+
const result = mockResult([playerCard, playerCard], [bankerCard, bankerCard], 8, 0, BaccaratOutcome.PLAYER_WIN);
|
|
438
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PERFECT_PAIR, 10)], result);
|
|
439
|
+
expect(payout.toNumber()).toBe(2010);
|
|
440
|
+
expect(multiplier.toNumber()).toBe(201);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('loses when player has a non-perfect pair and banker does not have a pair', () => {
|
|
444
|
+
const result = mockResult(
|
|
445
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
446
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
447
|
+
8,
|
|
448
|
+
5,
|
|
449
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
450
|
+
);
|
|
451
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PERFECT_PAIR, 10)], result);
|
|
452
|
+
expect(payout.toNumber()).toBe(0);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
describe('bonus side bets', () => {
|
|
457
|
+
it('P Bonus pays 1:1 on a natural player win', () => {
|
|
458
|
+
const result = mockResult(
|
|
459
|
+
[ci('8', Suits.CLUBS), ci('A', Suits.DIAMONDS)],
|
|
460
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
461
|
+
9,
|
|
462
|
+
5,
|
|
463
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
464
|
+
);
|
|
465
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
466
|
+
expect(payout.toNumber()).toBe(20);
|
|
467
|
+
expect(multiplier.toNumber()).toBe(2);
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
it('B Bonus pays 1:1 on a natural banker win', () => {
|
|
471
|
+
const result = mockResult(
|
|
472
|
+
[ci('3', Suits.CLUBS), ci('A', Suits.DIAMONDS)],
|
|
473
|
+
[ci('8', Suits.CLUBS), ci('A', Suits.CLUBS)],
|
|
474
|
+
4,
|
|
475
|
+
9,
|
|
476
|
+
BaccaratOutcome.BANKER_WIN,
|
|
477
|
+
);
|
|
478
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_BONUS, 10)], result);
|
|
479
|
+
expect(payout.toNumber()).toBe(20);
|
|
480
|
+
expect(multiplier.toNumber()).toBe(2);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('P Bonus loses when player loses', () => {
|
|
484
|
+
const result = mockResult(
|
|
485
|
+
[ci('3', Suits.CLUBS), ci('10', Suits.DIAMONDS), ci('Q', Suits.HEARTS)],
|
|
486
|
+
[ci('3', Suits.CLUBS), ci('4', Suits.DIAMONDS)],
|
|
487
|
+
3,
|
|
488
|
+
7,
|
|
489
|
+
BaccaratOutcome.BANKER_WIN,
|
|
490
|
+
);
|
|
491
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
492
|
+
expect(payout.toNumber()).toBe(0);
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
it('P Bonus loses on a non-natural win by fewer than 4 points', () => {
|
|
496
|
+
const result = mockResult(
|
|
497
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
498
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('3', Suits.HEARTS)],
|
|
499
|
+
7,
|
|
500
|
+
6,
|
|
501
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
502
|
+
);
|
|
503
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
504
|
+
expect(payout.toNumber()).toBe(0);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('P Bonus pays 1:1 on a non-natural banker win by 4', () => {
|
|
508
|
+
const result = mockResult(
|
|
509
|
+
[ci('4', Suits.CLUBS), ci('10', Suits.DIAMONDS), ci('Q', Suits.HEARTS)],
|
|
510
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('7', Suits.HEARTS)],
|
|
511
|
+
4,
|
|
512
|
+
0,
|
|
513
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
514
|
+
);
|
|
515
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
516
|
+
expect(payout.toNumber()).toBe(20);
|
|
517
|
+
expect(multiplier.toNumber()).toBe(2);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('B Bonus pays 2:1 on a non-natural banker win by 5', () => {
|
|
521
|
+
const result = mockResult(
|
|
522
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('8', Suits.HEARTS)],
|
|
523
|
+
[ci('3', Suits.DIAMONDS), ci('3', Suits.HEARTS)],
|
|
524
|
+
1,
|
|
525
|
+
6,
|
|
526
|
+
BaccaratOutcome.BANKER_WIN,
|
|
527
|
+
);
|
|
528
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_BONUS, 10)], result);
|
|
529
|
+
expect(payout.toNumber()).toBe(30);
|
|
530
|
+
expect(multiplier.toNumber()).toBe(3);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it('P Bonus pays 4:1 on non-natural win by 6', () => {
|
|
534
|
+
const result = mockResult(
|
|
535
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
536
|
+
[ci('A', Suits.CLUBS), ci('10', Suits.DIAMONDS), ci('Q', Suits.HEARTS)],
|
|
537
|
+
7,
|
|
538
|
+
1,
|
|
539
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
540
|
+
);
|
|
541
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
542
|
+
expect(payout.toNumber()).toBe(50);
|
|
543
|
+
expect(multiplier.toNumber()).toBe(5);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it('B Bonus pays 6:1 on a non-natural banker win by 7', () => {
|
|
547
|
+
const result = mockResult(
|
|
548
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('8', Suits.HEARTS)],
|
|
549
|
+
[ci('2', Suits.DIAMONDS), ci('A', Suits.HEARTS), ci('5', Suits.CLUBS)],
|
|
550
|
+
1,
|
|
551
|
+
8,
|
|
552
|
+
BaccaratOutcome.BANKER_WIN,
|
|
553
|
+
);
|
|
554
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_BONUS, 10)], result);
|
|
555
|
+
expect(payout.toNumber()).toBe(70);
|
|
556
|
+
expect(multiplier.toNumber()).toBe(7);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
it('P Bonus pays 10:1 on non-natural win by 8', () => {
|
|
560
|
+
const result = mockResult(
|
|
561
|
+
[ci('3', Suits.CLUBS), ci('A', Suits.DIAMONDS), ci('5', Suits.HEARTS)],
|
|
562
|
+
[ci('A', Suits.CLUBS), ci('A', Suits.DIAMONDS), ci('9', Suits.HEARTS)],
|
|
563
|
+
9,
|
|
564
|
+
1,
|
|
565
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
566
|
+
);
|
|
567
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.PLAYER_BONUS, 10)], result);
|
|
568
|
+
expect(payout.toNumber()).toBe(110);
|
|
569
|
+
expect(multiplier.toNumber()).toBe(11);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
it('B Bonus pays 30:1 on a non-natural banker win by 9', () => {
|
|
573
|
+
const result = mockResult(
|
|
574
|
+
[ci('A', Suits.CLUBS), ci('4', Suits.DIAMONDS), ci('5', Suits.HEARTS)],
|
|
575
|
+
[ci('3', Suits.DIAMONDS), ci('3', Suits.HEARTS), ci('3', Suits.CLUBS)],
|
|
576
|
+
0,
|
|
577
|
+
9,
|
|
578
|
+
BaccaratOutcome.BANKER_WIN,
|
|
579
|
+
);
|
|
580
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_BONUS, 10)], result);
|
|
581
|
+
expect(payout.toNumber()).toBe(310);
|
|
582
|
+
expect(multiplier.toNumber()).toBe(31);
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
it('B Bonus loses when player wins', () => {
|
|
586
|
+
const result = mockResult(
|
|
587
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
588
|
+
[ci('A', Suits.CLUBS), ci('A', Suits.DIAMONDS), ci('10', Suits.HEARTS)],
|
|
589
|
+
7,
|
|
590
|
+
2,
|
|
591
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
592
|
+
);
|
|
593
|
+
const { payout } = Baccarat.calcBetPayouts([bet(BaccaratBetType.BANKER_BONUS, 10)], result);
|
|
594
|
+
expect(payout.toNumber()).toBe(0);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
it('P Bonus and B Bonus both lose on a non-natural tie', () => {
|
|
598
|
+
const result = mockResult(
|
|
599
|
+
[ci('3', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
600
|
+
[ci('2', Suits.CLUBS), ci('4', Suits.DIAMONDS)],
|
|
601
|
+
6,
|
|
602
|
+
6,
|
|
603
|
+
BaccaratOutcome.TIE,
|
|
604
|
+
);
|
|
605
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
606
|
+
[bet(BaccaratBetType.PLAYER_BONUS, 10), bet(BaccaratBetType.BANKER_BONUS, 10)],
|
|
607
|
+
result,
|
|
608
|
+
);
|
|
609
|
+
expect(payout.toNumber()).toBe(0);
|
|
610
|
+
expect(multiplier.toNumber()).toBe(0);
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('both P Bonus and B Bonus push on natural tie', () => {
|
|
614
|
+
const result = mockResult(
|
|
615
|
+
[ci('8', Suits.CLUBS), ci('Q', Suits.DIAMONDS)],
|
|
616
|
+
[ci('8', Suits.DIAMONDS), ci('Q', Suits.HEARTS)],
|
|
617
|
+
8,
|
|
618
|
+
8,
|
|
619
|
+
BaccaratOutcome.TIE,
|
|
620
|
+
);
|
|
621
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
622
|
+
[bet(BaccaratBetType.PLAYER_BONUS, 10), bet(BaccaratBetType.BANKER_BONUS, 10)],
|
|
623
|
+
result,
|
|
624
|
+
);
|
|
625
|
+
expect(payout.toNumber()).toBe(20);
|
|
626
|
+
expect(multiplier.toNumber()).toBe(1);
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
describe('multiple simultaneous bets', () => {
|
|
631
|
+
it('player win + player pair + losing banker and tie bets: only winning bets contribute', () => {
|
|
632
|
+
const result = mockResult(
|
|
633
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
634
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
635
|
+
8,
|
|
636
|
+
5,
|
|
637
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
638
|
+
);
|
|
639
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
640
|
+
[bet(BaccaratBetType.PLAYER, 10), bet(BaccaratBetType.PLAYER_PAIR, 10), bet(BaccaratBetType.BANKER, 10), bet(BaccaratBetType.TIE, 10)],
|
|
641
|
+
result,
|
|
642
|
+
);
|
|
643
|
+
expect(payout.toNumber()).toBe(140);
|
|
644
|
+
expect(multiplier.toNumber()).toBe(3.5);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('player pair + either pair + losing banker pair: only player-side pair bets pay', () => {
|
|
648
|
+
const result = mockResult(
|
|
649
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
650
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
651
|
+
8,
|
|
652
|
+
5,
|
|
653
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
654
|
+
);
|
|
655
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
656
|
+
[bet(BaccaratBetType.PLAYER_PAIR, 10), bet(BaccaratBetType.EITHER_PAIR, 10), bet(BaccaratBetType.BANKER_PAIR, 10)],
|
|
657
|
+
result,
|
|
658
|
+
);
|
|
659
|
+
expect(payout.toNumber()).toBe(180);
|
|
660
|
+
expect(multiplier.toNumber()).toBe(6);
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('player pair + perfect pair + either pair + losing banker bet: all pair bets pay, main banker bet does not', () => {
|
|
664
|
+
const card = ci('4', Suits.CLUBS);
|
|
665
|
+
const result = mockResult([card, card], [ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)], 8, 5, BaccaratOutcome.PLAYER_WIN);
|
|
666
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
667
|
+
[
|
|
668
|
+
bet(BaccaratBetType.PLAYER_PAIR, 10),
|
|
669
|
+
bet(BaccaratBetType.PERFECT_PAIR, 10),
|
|
670
|
+
bet(BaccaratBetType.EITHER_PAIR, 10),
|
|
671
|
+
bet(BaccaratBetType.BANKER, 10),
|
|
672
|
+
],
|
|
673
|
+
result,
|
|
674
|
+
);
|
|
675
|
+
expect(payout.toNumber()).toBe(440);
|
|
676
|
+
expect(multiplier.toNumber()).toBe(11);
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('player pair + banker pair + perfect pair: all three pay when both hands have perfect pairs', () => {
|
|
680
|
+
const playerCard = ci('4', Suits.CLUBS);
|
|
681
|
+
const bankerCard = ci('K', Suits.DIAMONDS);
|
|
682
|
+
const result = mockResult([playerCard, playerCard], [bankerCard, bankerCard], 8, 0, BaccaratOutcome.PLAYER_WIN);
|
|
683
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
684
|
+
[bet(BaccaratBetType.PLAYER_PAIR, 10), bet(BaccaratBetType.BANKER_PAIR, 10), bet(BaccaratBetType.PERFECT_PAIR, 10)],
|
|
685
|
+
result,
|
|
686
|
+
);
|
|
687
|
+
expect(payout.toNumber()).toBe(2250);
|
|
688
|
+
expect(multiplier.toNumber()).toBe(75);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
it('player pair + banker pair + either pair + tie bet + player push on natural tie: pair and tie win, player pushes', () => {
|
|
692
|
+
const result = mockResult(
|
|
693
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
694
|
+
[ci('9', Suits.DIAMONDS), ci('9', Suits.HEARTS)],
|
|
695
|
+
8,
|
|
696
|
+
8,
|
|
697
|
+
BaccaratOutcome.TIE,
|
|
698
|
+
);
|
|
699
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
700
|
+
[
|
|
701
|
+
bet(BaccaratBetType.PLAYER_PAIR, 10),
|
|
702
|
+
bet(BaccaratBetType.BANKER_PAIR, 10),
|
|
703
|
+
bet(BaccaratBetType.EITHER_PAIR, 10),
|
|
704
|
+
bet(BaccaratBetType.TIE, 10),
|
|
705
|
+
bet(BaccaratBetType.PLAYER, 10),
|
|
706
|
+
],
|
|
707
|
+
result,
|
|
708
|
+
);
|
|
709
|
+
expect(payout.toNumber()).toBe(400);
|
|
710
|
+
expect(multiplier.toNumber()).toBe(8);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
it('player bonus + player pair + losing banker-side bets: only player-side bets pay', () => {
|
|
714
|
+
const result = mockResult(
|
|
715
|
+
[ci('4', Suits.CLUBS), ci('4', Suits.HEARTS)],
|
|
716
|
+
[ci('3', Suits.CLUBS), ci('2', Suits.DIAMONDS)],
|
|
717
|
+
8,
|
|
718
|
+
5,
|
|
719
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
720
|
+
);
|
|
721
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
722
|
+
[
|
|
723
|
+
bet(BaccaratBetType.PLAYER_BONUS, 10),
|
|
724
|
+
bet(BaccaratBetType.PLAYER_PAIR, 10),
|
|
725
|
+
bet(BaccaratBetType.BANKER_BONUS, 10),
|
|
726
|
+
bet(BaccaratBetType.BANKER_PAIR, 10),
|
|
727
|
+
],
|
|
728
|
+
result,
|
|
729
|
+
);
|
|
730
|
+
expect(payout.toNumber()).toBe(140);
|
|
731
|
+
expect(multiplier.toNumber()).toBe(3.5);
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
it('player pair + player bonus + losing banker and banker bonus: opposite-side bets contribute zero', () => {
|
|
735
|
+
const result = mockResult(
|
|
736
|
+
[ci('7', Suits.CLUBS), ci('7', Suits.HEARTS), ci('2', Suits.DIAMONDS)],
|
|
737
|
+
[ci('10', Suits.CLUBS), ci('Q', Suits.DIAMONDS), ci('10', Suits.HEARTS)],
|
|
738
|
+
6,
|
|
739
|
+
0,
|
|
740
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
741
|
+
);
|
|
742
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
743
|
+
[
|
|
744
|
+
bet(BaccaratBetType.PLAYER_PAIR, 10),
|
|
745
|
+
bet(BaccaratBetType.PLAYER_BONUS, 10),
|
|
746
|
+
bet(BaccaratBetType.BANKER, 10),
|
|
747
|
+
bet(BaccaratBetType.BANKER_BONUS, 10),
|
|
748
|
+
],
|
|
749
|
+
result,
|
|
750
|
+
);
|
|
751
|
+
expect(payout.toNumber()).toBe(170);
|
|
752
|
+
expect(multiplier.toNumber()).toBe(4.25);
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
it('banker pair + banker bonus + all losing player-side bets: only banker bets pay', () => {
|
|
756
|
+
const result = mockResult(
|
|
757
|
+
[ci('A', Suits.CLUBS), ci('2', Suits.DIAMONDS), ci('8', Suits.HEARTS)],
|
|
758
|
+
[ci('3', Suits.DIAMONDS), ci('3', Suits.HEARTS)],
|
|
759
|
+
1,
|
|
760
|
+
6,
|
|
761
|
+
BaccaratOutcome.BANKER_WIN,
|
|
762
|
+
);
|
|
763
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
764
|
+
[
|
|
765
|
+
bet(BaccaratBetType.BANKER_PAIR, 10),
|
|
766
|
+
bet(BaccaratBetType.BANKER_BONUS, 10),
|
|
767
|
+
bet(BaccaratBetType.PLAYER, 10),
|
|
768
|
+
bet(BaccaratBetType.TIE, 10),
|
|
769
|
+
bet(BaccaratBetType.PLAYER_PAIR, 10),
|
|
770
|
+
bet(BaccaratBetType.PLAYER_BONUS, 10),
|
|
771
|
+
],
|
|
772
|
+
result,
|
|
773
|
+
);
|
|
774
|
+
expect(payout.toNumber()).toBe(150);
|
|
775
|
+
expect(multiplier.toNumber()).toBe(2.5);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
it('losing main banker bet + winning banker pair + other losing bets: only banker pair pays', () => {
|
|
779
|
+
const result = mockResult(
|
|
780
|
+
[ci('4', Suits.CLUBS), ci('3', Suits.DIAMONDS)],
|
|
781
|
+
[ci('6', Suits.DIAMONDS), ci('6', Suits.HEARTS), ci('10', Suits.CLUBS)],
|
|
782
|
+
7,
|
|
783
|
+
2,
|
|
784
|
+
BaccaratOutcome.PLAYER_WIN,
|
|
785
|
+
);
|
|
786
|
+
const { payout, multiplier } = Baccarat.calcBetPayouts(
|
|
787
|
+
[bet(BaccaratBetType.BANKER, 10), bet(BaccaratBetType.BANKER_PAIR, 10), bet(BaccaratBetType.TIE, 10), bet(BaccaratBetType.PLAYER_PAIR, 10)],
|
|
788
|
+
result,
|
|
789
|
+
);
|
|
790
|
+
expect(payout.toNumber()).toBe(120);
|
|
791
|
+
expect(multiplier.toNumber()).toBe(3);
|
|
792
|
+
});
|
|
793
|
+
});
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
describe('getGameOutcome', () => {
|
|
797
|
+
it('returns result, payout, and multiplier for a valid game', () => {
|
|
798
|
+
const hex = hexString(SEED1.serverSeed, SEED1.clientSeed, '2');
|
|
799
|
+
const { result, payout, multiplier } = Baccarat.getGameOutcome([bet(BaccaratBetType.BANKER, 100)], hex);
|
|
800
|
+
expect(result.outcome).toBe(BaccaratOutcome.BANKER_WIN);
|
|
801
|
+
expect(payout.toNumber()).toBe(195);
|
|
802
|
+
expect(multiplier.toNumber()).toBe(1.95);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
});
|