@adiakys/feeling-lucky 0.1.0 → 0.3.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.
Files changed (50) hide show
  1. package/README.md +73 -5
  2. package/dist/config/types.d.ts +11 -0
  3. package/dist/{de-Cp-ILcpM.js → de-CmzpGbNK.js} +19 -3
  4. package/dist/developer/panel.d.ts +2 -0
  5. package/dist/developer/settings.d.ts +2 -0
  6. package/dist/engine/dealer.d.ts +21 -0
  7. package/dist/{es-DHZIstf4.js → es-k_kS6Fn2.js} +19 -3
  8. package/dist/feeling-lucky.iife.js +417 -249
  9. package/dist/feeling-lucky.js +17 -39
  10. package/dist/{fr-BPFoerSF.js → fr-GuCZB1l4.js} +19 -3
  11. package/dist/games/blackjack/blackjack.d.ts +1 -0
  12. package/dist/games/cards/dealer.d.ts +9 -0
  13. package/dist/games/cards/table.d.ts +7 -1
  14. package/dist/games/holdem/holdem.d.ts +2 -0
  15. package/dist/{i18n-CihzHMU5.js → i18n-Cid8bj2R.js} +23 -7
  16. package/dist/icons-DTaPp44c.js +863 -0
  17. package/dist/{it-B95CFDto.js → it-BNztlqHd.js} +19 -3
  18. package/dist/locales/de/cards.d.ts +7 -0
  19. package/dist/locales/de/developer.d.ts +7 -0
  20. package/dist/locales/de/room.d.ts +2 -0
  21. package/dist/locales/en/cards.d.ts +7 -0
  22. package/dist/locales/en/developer.d.ts +7 -0
  23. package/dist/locales/en/room.d.ts +2 -0
  24. package/dist/locales/es/cards.d.ts +7 -0
  25. package/dist/locales/es/developer.d.ts +7 -0
  26. package/dist/locales/es/room.d.ts +2 -0
  27. package/dist/locales/fr/cards.d.ts +7 -0
  28. package/dist/locales/fr/developer.d.ts +7 -0
  29. package/dist/locales/fr/room.d.ts +2 -0
  30. package/dist/locales/it/cards.d.ts +7 -0
  31. package/dist/locales/it/developer.d.ts +7 -0
  32. package/dist/locales/it/room.d.ts +2 -0
  33. package/dist/mount-CMm0qSYk.js +6257 -0
  34. package/dist/multiplayer/blackjack.d.ts +35 -0
  35. package/dist/multiplayer/client.d.ts +55 -0
  36. package/dist/multiplayer/holdem.d.ts +21 -0
  37. package/dist/multiplayer/index.d.ts +2 -0
  38. package/dist/multiplayer/seats.d.ts +16 -0
  39. package/dist/multiplayer/shared.d.ts +33 -0
  40. package/dist/multiplayer-CN0t0j_F.js +502 -0
  41. package/dist/{panel-D1hKmQL7.js → panel-BVgq3Cm5.js} +167 -139
  42. package/dist/resolve-Dc48n2Jo.js +28 -0
  43. package/dist/room/boost.d.ts +1 -1
  44. package/dist/room/lobby.d.ts +1 -0
  45. package/dist/room/room.d.ts +11 -1
  46. package/dist/room/stage.d.ts +2 -1
  47. package/dist/runtime/context.d.ts +3 -1
  48. package/dist/runtime/sound.d.ts +1 -1
  49. package/package.json +2 -2
  50. package/dist/mount-BxDaFww2.js +0 -7034
package/README.md CHANGED
@@ -64,10 +64,12 @@ Every field takes a value, a function, or a function returning a Promise.
64
64
  | `locale` | language code, e.g. `'it'` or `'pt-BR'` | follows the host page, see [Languages](#languages) |
65
65
  | `messages` | `{ [locale]: Messages }`: new languages, or overrides of the built-in ones | none |
66
66
  | `logo` | image URL of your brand mark, on the certificate, the wheel's hub and the scratch card | a clover |
67
+ | `dealers` | `Dealer[]`: the dealers who take the Salon Privé's shifts, see [Dealers](#dealers) | the library's own dealer |
67
68
  | `player` | `{ name, avatar? }`, shown at the card tables | anonymous seat |
68
69
  | `onWin` | `(win: Win) => void` | none |
69
70
  | `onClaim` | `(win: Win) => Promise<void>`; shows **Claim** on the certificate | no claim button |
70
71
  | `developer` | `true` or `{ passwordHash? }`: enables the developer menu (Ctrl+Shift+L), behind a password when the hash is given | disabled |
72
+ | `multiplayer` | base URL of a [multiplayer server](#multiplayer), or `{ url, headers? }` | single player |
71
73
 
72
74
  ```ts
73
75
  interface Prize {
@@ -159,8 +161,72 @@ createFeelingLucky({
159
161
  - Takeoff or Breakaway in place of the slot
160
162
  - Double Luck or Forever in place of the scratch card
161
163
  - colour Pachinko
164
+ - **Dealers:** three shifts a day, the same for everyone, from the date's hash, see [Dealers](#dealers).
162
165
  - **Room themes:** Christmas, Halloween, Easter and August, taken from the calendar.
163
166
 
167
+ ## Dealers
168
+
169
+ A dealer stands at the Salon Privé's tables during three shifts a day of 30 to 90 minutes between 10:00 and 23:00, local time. The shifts come from the date's hash, and the dealers in the list take them in turn. While a dealer is on shift, Blackjack and Texas Hold'em win twice as often. A dealer arriving or leaving mid-game walks in or out of the table, and the odds change from the next hand.
170
+
171
+ ```ts
172
+ interface Dealer {
173
+ image: string; // waist-up portrait, transparent background, forearms resting forward at the bottom
174
+ name?: string;
175
+ hands?: string; // CSS clip-path of the forearms and hands, drawn over the table's rim
176
+ }
177
+ ```
178
+
179
+ Without `dealers`, the library's own illustrated dealer takes every shift; `dealers: []` leaves the tables without one.
180
+
181
+ ## Multiplayer
182
+
183
+ Optional: with `multiplayer`, Blackjack and Texas Hold'em are played at shared tables, one per game, up to five players, each against the house.
184
+
185
+ - **Seats:** players watch from the rail and pick a free seat, the same places for everyone; they can move or stand up between hands. A browser holds one seat per table, whatever its tabs; a signed-in user holds one across devices.
186
+ - **Outcomes:** the server deals and draws them, with the same odds as single player, a dealer's bonus included; wins still reach `onWin` and `onClaim` in each player's browser.
187
+ - **Fallback:** without the server the room plays single player; the developer menu switches between the two.
188
+ - **Size:** the client code loads only when `multiplayer` is set.
189
+
190
+ ```ts
191
+ createFeelingLucky({ prizes, multiplayer: '/feeling-lucky' });
192
+
193
+ createFeelingLucky({
194
+ prizes,
195
+ multiplayer: { url: 'https://tables.example.com/feeling-lucky', headers: async () => ({ Authorization: `Bearer ${await token()}` }) },
196
+ });
197
+ ```
198
+
199
+ `headers` is asked for again on every request. On the same origin the browser's cookies go along, so the server sees the signed-in user.
200
+
201
+ ### Server
202
+
203
+ In your ASP.NET Core app, from NuGet:
204
+
205
+ ```bash
206
+ dotnet add package Adiakys.FeelingLucky
207
+ ```
208
+
209
+ ```cs
210
+ builder.Services.AddFeelingLucky();
211
+ app.MapFeelingLucky(); // /feeling-lucky, chain .RequireAuthorization() or .RequireCors() as needed
212
+ ```
213
+
214
+ Or standalone, from the container:
215
+
216
+ ```bash
217
+ docker run -p 8080:8080 -e Cors__Origins__0=https://app.example.com ghcr.io/adiakys/feeling-lucky-server
218
+ ```
219
+
220
+ | Option (`FeelingLucky__*` in the container) | Default |
221
+ |---|---|
222
+ | `Seats` | 5 |
223
+ | `Pace`: the time between two cards | 480 ms |
224
+ | `BettingTime`: from the first bet to the deal | 10 s |
225
+ | `ActionTime`: to hit, stand, call or fold | 20 s |
226
+ | `TimeZone`: the dealers' shifts, IANA id | the server's |
227
+
228
+ Tables live in memory: one instance, no storage.
229
+
164
230
  ## Structure
165
231
 
166
232
  ```
@@ -178,6 +244,7 @@ src/
178
244
  locales/ en, it, es, fr, de
179
245
  playground/ demo with sample prizes
180
246
  tests/ unit (engine), e2e
247
+ server/ multiplayer server: the NuGet package, the standalone host, tests
181
248
  ```
182
249
 
183
250
  ### Rules
@@ -191,7 +258,7 @@ tests/ unit (engine), e2e
191
258
 
192
259
  ```bash
193
260
  npm install
194
- npm run dev # playground
261
+ npm run dev # playground; multiplayer through docker compose up -d
195
262
  npm test # unit tests
196
263
  npm run test:e2e # one smoke test per game
197
264
  npm run typecheck
@@ -201,11 +268,12 @@ npm run build:demo # site/: the playground, as on GitHub Pages
201
268
 
202
269
  ## Release
203
270
 
204
- Bump `version` in `package.json`, then push a `v<version>` tag. The release workflow:
271
+ Publish a GitHub release or pre-release on a `v<version>` tag, e.g. `v1.2.0` or `v1.3.0-beta.1`: the version comes from the tag, `package.json` only holds a placeholder. The release workflow:
205
272
  - runs the checks;
206
- - publishes the package to npm;
207
- - attaches the packed `.tgz` to a GitHub release;
208
- - deploys the playground to GitHub Pages.
273
+ - publishes the package to npm: `latest` for a release, `next` for a pre-release;
274
+ - attaches the packed `.tgz` to the release;
275
+ - publishes the server to NuGet through Trusted Publishing, and its image to `ghcr.io/adiakys/feeling-lucky-server`, `latest` for a release;
276
+ - deploys the playground to GitHub Pages, for releases only.
209
277
 
210
278
  ## License
211
279
 
@@ -24,10 +24,19 @@ export interface Win<V extends Variant = Variant> {
24
24
  tier: PrizeTier;
25
25
  game: GameId;
26
26
  }
27
+ export interface Dealer {
28
+ image: string;
29
+ name?: string;
30
+ hands?: string;
31
+ }
27
32
  export interface Player {
28
33
  name: string;
29
34
  avatar?: string;
30
35
  }
36
+ export interface Multiplayer {
37
+ url: string;
38
+ headers?: Resolvable<Record<string, string>>;
39
+ }
31
40
  export type Messages = {
32
41
  [key: string]: string | Messages;
33
42
  };
@@ -37,11 +46,13 @@ export interface FeelingLuckyConfig<V extends Variant = Variant> {
37
46
  messages?: Resolvable<Record<string, Messages>>;
38
47
  player?: Resolvable<Player>;
39
48
  logo?: Resolvable<string>;
49
+ dealers?: Resolvable<Dealer[]>;
40
50
  onWin?: (win: Win<V>) => void;
41
51
  onClaim?: (win: Win<V>) => Promise<void>;
42
52
  developer?: Resolvable<boolean | {
43
53
  passwordHash?: string;
44
54
  }>;
55
+ multiplayer?: Resolvable<string | Multiplayer>;
45
56
  }
46
57
  export interface FeelingLucky<V extends Variant = Variant> {
47
58
  open(options?: {
@@ -34,7 +34,9 @@ var t = e({
34
34
  boost: {
35
35
  badge: "×{n}",
36
36
  title: "Bonus des Tages",
37
- odds: "Bonus des Tages: Gewinne {n}-mal so wahrscheinlich"
37
+ odds: "Bonus des Tages: Gewinne {n}-mal so wahrscheinlich",
38
+ dealer: "Croupier am Tisch",
39
+ dealerOdds: "Croupier am Tisch: Gewinne {n}-mal so wahrscheinlich"
38
40
  },
39
41
  themes: {
40
42
  christmas: {
@@ -335,7 +337,14 @@ var t = e({
335
337
  cards: {
336
338
  you: "Du",
337
339
  dealer: "Bank",
338
- deal: "Geben"
340
+ deal: "Geben",
341
+ player: "Spieler",
342
+ stand: "Vom Tisch aufstehen",
343
+ sit: "Hier hinsetzen",
344
+ chooseSeat: "Wähle einen Platz",
345
+ dealingIn: "Neue Hand in {seconds}s",
346
+ playIn: "{seconds}s zum Spielen",
347
+ nextHand: "Du spielst ab der nächsten Hand"
339
348
  },
340
349
  blackjack: {
341
350
  print: "Bank steht bei 17 · Pik-Blackjack: Jackpot",
@@ -447,6 +456,13 @@ var t = e({
447
456
  calendar: "Nach Kalender",
448
457
  noTheme: "Keins",
449
458
  language: "Sprache",
450
- autoLanguage: "Automatisch"
459
+ autoLanguage: "Automatisch",
460
+ tables: "Kartentische",
461
+ multiplayer: "Mehrspieler",
462
+ singlePlayer: "Einzelspieler",
463
+ dealer: "Croupier",
464
+ dealerShifts: "Nach den Schichten des Tages",
465
+ dealerAbsent: "Abwesend",
466
+ dealerNumber: "Croupier {n}"
451
467
  } });
452
468
  export { t as default };
@@ -36,6 +36,8 @@ export declare class Developer extends LuckyElement {
36
36
  private reset;
37
37
  private toggle;
38
38
  private setLanguage;
39
+ private setDealer;
40
+ private setTables;
39
41
  private setTheme;
40
42
  private shortcut;
41
43
  private keydown;
@@ -16,6 +16,8 @@ export declare const settings: Partial<Record<GameId, GameSettings>>;
16
16
  export declare const room: {
17
17
  theme?: Theme | 'none';
18
18
  locale?: string;
19
+ dealer?: number | 'none';
20
+ singlePlayer?: boolean;
19
21
  prizes: Prize[];
20
22
  };
21
23
  export declare const blankSettings: () => GameSettings;
@@ -0,0 +1,21 @@
1
+ declare module './rig' {
2
+ interface Decisions {
3
+ dealer: {
4
+ context: {
5
+ count: number;
6
+ };
7
+ value: number | null;
8
+ };
9
+ }
10
+ }
11
+ export declare const DEALER_BOOST = 2;
12
+ export interface Shift {
13
+ start: number;
14
+ end: number;
15
+ dealer: number;
16
+ }
17
+ export declare function dealerShifts(date: Date, count: number): Shift[];
18
+ export declare function shiftAt(date: Date, count: number): number | null;
19
+ export declare const roster: import("../runtime/signal").Signal<number>;
20
+ export declare const onDuty: import("../runtime/signal").Signal<number | null>;
21
+ export declare function checkDuty(now?: Date): void;
@@ -34,7 +34,9 @@ var t = e({
34
34
  boost: {
35
35
  badge: "×{n}",
36
36
  title: "Bonus del día",
37
- odds: "Bonus del día: premios {n} veces más probables"
37
+ odds: "Bonus del día: premios {n} veces más probables",
38
+ dealer: "Crupier en la mesa",
39
+ dealerOdds: "Crupier en la mesa: premios {n} veces más probables"
38
40
  },
39
41
  themes: {
40
42
  christmas: {
@@ -335,7 +337,14 @@ var t = e({
335
337
  cards: {
336
338
  you: "Tú",
337
339
  dealer: "Banca",
338
- deal: "Repartir"
340
+ deal: "Repartir",
341
+ player: "Jugador",
342
+ stand: "Levantarse de la mesa",
343
+ sit: "Siéntate aquí",
344
+ chooseSeat: "Elige un asiento",
345
+ dealingIn: "Se reparte en {seconds}s",
346
+ playIn: "{seconds}s para jugar",
347
+ nextHand: "Juegas desde la próxima mano"
339
348
  },
340
349
  blackjack: {
341
350
  print: "Banca se planta en 17 · Blackjack de picas: jackpot",
@@ -447,6 +456,13 @@ var t = e({
447
456
  calendar: "Según el calendario",
448
457
  noTheme: "Ninguno",
449
458
  language: "Idioma",
450
- autoLanguage: "Automático"
459
+ autoLanguage: "Automático",
460
+ tables: "Mesas de cartas",
461
+ multiplayer: "Multijugador",
462
+ singlePlayer: "Un jugador",
463
+ dealer: "Crupier",
464
+ dealerShifts: "Según los turnos del día",
465
+ dealerAbsent: "Ausente",
466
+ dealerNumber: "Crupier {n}"
451
467
  } });
452
468
  export { t as default };