@hellacardgames/speed 0.9.1 → 0.10.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/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/{ClientState-Dx8UvhMt.d.cts → index-89KVb2dD.d.cts} +2 -8
- package/dist/index-89KVb2dD.d.cts.map +1 -0
- package/dist/{ClientState-Dx8UvhMt.d.mts → index-89KVb2dD.d.mts} +2 -8
- package/dist/index-89KVb2dD.d.mts.map +1 -0
- package/dist/manager/index.cjs +1 -1
- package/dist/manager/index.d.cts +4 -4
- package/dist/manager/index.d.cts.map +1 -1
- package/dist/manager/index.d.mts +4 -4
- package/dist/manager/index.d.mts.map +1 -1
- package/dist/manager/index.mjs +1 -1
- package/dist/{manager-C6MB3C6o.cjs → manager-49xVpBPl.cjs} +30 -57
- package/dist/manager-49xVpBPl.cjs.map +1 -0
- package/dist/{manager-B7nTzkpn.mjs → manager-BYLO6oGT.mjs} +31 -58
- package/dist/manager-BYLO6oGT.mjs.map +1 -0
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +2 -2
- package/dist/ClientState-Dx8UvhMt.d.cts.map +0 -1
- package/dist/ClientState-Dx8UvhMt.d.mts.map +0 -1
- package/dist/manager-B7nTzkpn.mjs.map +0 -1
- package/dist/manager-C6MB3C6o.cjs.map +0 -1
package/dist/client/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as Card, n as GameEvent, r as ChatMessage, t as ClientState } from "../
|
|
1
|
+
import { i as Card, n as GameEvent, r as ChatMessage, t as ClientState } from "../index-89KVb2dD.cjs";
|
|
2
2
|
//#region src/client/Client.d.ts
|
|
3
3
|
declare class Client {
|
|
4
4
|
private readonly baseUrl;
|
package/dist/client/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as Card, n as GameEvent, r as ChatMessage, t as ClientState } from "../
|
|
1
|
+
import { i as Card, n as GameEvent, r as ChatMessage, t as ClientState } from "../index-89KVb2dD.mjs";
|
|
2
2
|
//#region src/client/Client.d.ts
|
|
3
3
|
declare class Client {
|
|
4
4
|
private readonly baseUrl;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ChatMessage } from "@hellacardgames/lib";
|
|
1
2
|
//#region src/game/types/Card.d.ts
|
|
2
3
|
type Card = {
|
|
3
4
|
readonly id: string;
|
|
@@ -5,13 +6,6 @@ type Card = {
|
|
|
5
6
|
readonly suite: "clubs" | "diamonds" | "hearts" | "spades";
|
|
6
7
|
};
|
|
7
8
|
//#endregion
|
|
8
|
-
//#region src/game/types/ChatMessage.d.ts
|
|
9
|
-
type ChatMessage = {
|
|
10
|
-
readonly id: string;
|
|
11
|
-
readonly username: string;
|
|
12
|
-
readonly text: string;
|
|
13
|
-
};
|
|
14
|
-
//#endregion
|
|
15
9
|
//#region src/game/types/GameEvent.d.ts
|
|
16
10
|
type GameEvent = {
|
|
17
11
|
readonly type: "canPlayAtUpdated";
|
|
@@ -108,4 +102,4 @@ type Player = {
|
|
|
108
102
|
};
|
|
109
103
|
//#endregion
|
|
110
104
|
export { Card as i, GameEvent as n, ChatMessage as r, ClientState as t };
|
|
111
|
-
//# sourceMappingURL=
|
|
105
|
+
//# sourceMappingURL=index-89KVb2dD.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-89KVb2dD.d.cts","names":[],"sources":["../src/game/types/Card.ts","../src/game/types/GameEvent.ts","../src/game/types/ClientState.ts"],"mappings":";;KAAY;WACD;WACA;WACA;;;;KCAC;WAEG;WACA;WACA;;WAGA;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA,MAAM;WACN;;WAGA;WACA;WACA,SAAS;;WAGT;WACA;WACA,MAAM;;WAGN;WACA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WACA,gBAAgB;;WAGhB;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;;;KCxFH;WACD;WACA;WACA;WACA;WACA,kBAAkB;WAClB;WACA,uBAAuB;WACvB,eAAe;WACf;;KAGN;WACM;WACA;WACA;WACA;WACA,mBAAmB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ChatMessage } from "@hellacardgames/lib";
|
|
1
2
|
//#region src/game/types/Card.d.ts
|
|
2
3
|
type Card = {
|
|
3
4
|
readonly id: string;
|
|
@@ -5,13 +6,6 @@ type Card = {
|
|
|
5
6
|
readonly suite: "clubs" | "diamonds" | "hearts" | "spades";
|
|
6
7
|
};
|
|
7
8
|
//#endregion
|
|
8
|
-
//#region src/game/types/ChatMessage.d.ts
|
|
9
|
-
type ChatMessage = {
|
|
10
|
-
readonly id: string;
|
|
11
|
-
readonly username: string;
|
|
12
|
-
readonly text: string;
|
|
13
|
-
};
|
|
14
|
-
//#endregion
|
|
15
9
|
//#region src/game/types/GameEvent.d.ts
|
|
16
10
|
type GameEvent = {
|
|
17
11
|
readonly type: "canPlayAtUpdated";
|
|
@@ -108,4 +102,4 @@ type Player = {
|
|
|
108
102
|
};
|
|
109
103
|
//#endregion
|
|
110
104
|
export { Card as i, GameEvent as n, ChatMessage as r, ClientState as t };
|
|
111
|
-
//# sourceMappingURL=
|
|
105
|
+
//# sourceMappingURL=index-89KVb2dD.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-89KVb2dD.d.mts","names":[],"sources":["../src/game/types/Card.ts","../src/game/types/GameEvent.ts","../src/game/types/ClientState.ts"],"mappings":";;KAAY;WACD;WACA;WACA;;;;KCAC;WAEG;WACA;WACA;;WAGA;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA,MAAM;WACN;;WAGA;WACA;WACA,SAAS;;WAGT;WACA;WACA,MAAM;;WAGN;WACA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WACA,gBAAgB;;WAGhB;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;;;KCxFH;WACD;WACA;WACA;WACA;WACA,kBAAkB;WAClB;WACA,uBAAuB;WACvB,eAAe;WACf;;KAGN;WACM;WACA;WACA;WACA;WACA,mBAAmB"}
|
package/dist/manager/index.cjs
CHANGED
package/dist/manager/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as GameEvent, t as ClientState } from "../
|
|
1
|
+
import { n as GameEvent, t as ClientState } from "../index-89KVb2dD.cjs";
|
|
2
2
|
//#region src/manager/createManager.d.ts
|
|
3
3
|
declare const createManager: (logKey: string, maxGames: number, watchdogIntervalMs: number) => {
|
|
4
4
|
readonly createGame: (userId: string, username: string) => {
|
|
@@ -74,12 +74,12 @@ declare const createManager: (logKey: string, maxGames: number, watchdogInterval
|
|
|
74
74
|
readonly sendChat: (gameId: string, playerId: string, text: string) => {
|
|
75
75
|
readonly success: false;
|
|
76
76
|
readonly error: "gameNotFound";
|
|
77
|
-
} | {
|
|
78
|
-
readonly success: true;
|
|
79
|
-
readonly error?: never;
|
|
80
77
|
} | {
|
|
81
78
|
readonly success: false;
|
|
82
79
|
readonly error: "playerNotFound";
|
|
80
|
+
} | {
|
|
81
|
+
readonly success: true;
|
|
82
|
+
readonly error?: never;
|
|
83
83
|
};
|
|
84
84
|
readonly startGame: (gameId: string, playerId: string) => {
|
|
85
85
|
readonly success: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/manager/createManager.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/manager/createManager.ts"],"mappings":";;cAca,gBAAa,gBAAA,kBAAA;;;;aA6DqhE;aAA+B;;;;;aAA4H;;;;;;;;;;;;oBA7D7rE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6D8pI;;;;;;;;;;;;;;;;EApDppI,WAAA,gBAAM;;;;;;;;;;;;;EAgBf,WAAA,gBAAM,kBACE,gBACF;;;;;;;;;;;;;EAiBgB,wBAAA,gBAAM"}
|
package/dist/manager/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as GameEvent, t as ClientState } from "../
|
|
1
|
+
import { n as GameEvent, t as ClientState } from "../index-89KVb2dD.mjs";
|
|
2
2
|
//#region src/manager/createManager.d.ts
|
|
3
3
|
declare const createManager: (logKey: string, maxGames: number, watchdogIntervalMs: number) => {
|
|
4
4
|
readonly createGame: (userId: string, username: string) => {
|
|
@@ -74,12 +74,12 @@ declare const createManager: (logKey: string, maxGames: number, watchdogInterval
|
|
|
74
74
|
readonly sendChat: (gameId: string, playerId: string, text: string) => {
|
|
75
75
|
readonly success: false;
|
|
76
76
|
readonly error: "gameNotFound";
|
|
77
|
-
} | {
|
|
78
|
-
readonly success: true;
|
|
79
|
-
readonly error?: never;
|
|
80
77
|
} | {
|
|
81
78
|
readonly success: false;
|
|
82
79
|
readonly error: "playerNotFound";
|
|
80
|
+
} | {
|
|
81
|
+
readonly success: true;
|
|
82
|
+
readonly error?: never;
|
|
83
83
|
};
|
|
84
84
|
readonly startGame: (gameId: string, playerId: string) => {
|
|
85
85
|
readonly success: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/manager/createManager.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/manager/createManager.ts"],"mappings":";;cAca,gBAAa,gBAAA,kBAAA;;;;aA6DqhE;aAA+B;;;;;aAA4H;;;;;;;;;;;;oBA7D7rE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6D8pI;;;;;;;;;;;;;;;;EApDppI,WAAA,gBAAM;;;;;;;;;;;;;EAgBf,WAAA,gBAAM,kBACE,gBACF;;;;;;;;;;;;;EAiBgB,wBAAA,gBAAM"}
|
package/dist/manager/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createManager } from "../manager-
|
|
1
|
+
import { t as createManager } from "../manager-BYLO6oGT.mjs";
|
|
2
2
|
export { createManager };
|
|
@@ -293,7 +293,7 @@ function createGame(userId, username) {
|
|
|
293
293
|
}
|
|
294
294
|
//#endregion
|
|
295
295
|
//#region src/game/lib/emitEvent.ts
|
|
296
|
-
function emitEvent
|
|
296
|
+
function emitEvent(game, data) {
|
|
297
297
|
const event = {
|
|
298
298
|
...data,
|
|
299
299
|
id: crypto.randomUUID()
|
|
@@ -329,7 +329,7 @@ function drawCard(game, playerId) {
|
|
|
329
329
|
error: "drawPileEmpty"
|
|
330
330
|
};
|
|
331
331
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
332
|
-
emitEvent
|
|
332
|
+
emitEvent(game, {
|
|
333
333
|
type: "expirationUpdated",
|
|
334
334
|
expiresAt: game.expiresAt
|
|
335
335
|
});
|
|
@@ -339,7 +339,7 @@ function drawCard(game, playerId) {
|
|
|
339
339
|
type: "drewCard",
|
|
340
340
|
card
|
|
341
341
|
});
|
|
342
|
-
emitEvent
|
|
342
|
+
emitEvent(game, {
|
|
343
343
|
type: "playerDrewCard",
|
|
344
344
|
username: player.username
|
|
345
345
|
});
|
|
@@ -418,7 +418,7 @@ function joinGame(game, userId, username) {
|
|
|
418
418
|
hasNoPlayableCards: false
|
|
419
419
|
};
|
|
420
420
|
game.players.push(player);
|
|
421
|
-
emitEvent
|
|
421
|
+
emitEvent(game, {
|
|
422
422
|
type: "playerJoined",
|
|
423
423
|
username
|
|
424
424
|
});
|
|
@@ -437,7 +437,7 @@ function leaveGame(game, playerId) {
|
|
|
437
437
|
error: "playerNotFound"
|
|
438
438
|
};
|
|
439
439
|
const player = game.players[playerIndex];
|
|
440
|
-
emitEvent
|
|
440
|
+
emitEvent(game, {
|
|
441
441
|
type: "playerLeft",
|
|
442
442
|
username: player.username
|
|
443
443
|
});
|
|
@@ -448,8 +448,8 @@ function leaveGame(game, playerId) {
|
|
|
448
448
|
status: "forfeited",
|
|
449
449
|
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
450
450
|
};
|
|
451
|
-
emitEvent
|
|
452
|
-
emitEvent
|
|
451
|
+
emitEvent(forfeitedGame, { type: "gameForfeited" });
|
|
452
|
+
emitEvent(forfeitedGame, {
|
|
453
453
|
type: "expirationUpdated",
|
|
454
454
|
expiresAt: forfeitedGame.expiresAt
|
|
455
455
|
});
|
|
@@ -503,13 +503,13 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
503
503
|
error: "cardNotPlayable"
|
|
504
504
|
};
|
|
505
505
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
506
|
-
emitEvent
|
|
506
|
+
emitEvent(game, {
|
|
507
507
|
type: "expirationUpdated",
|
|
508
508
|
expiresAt: game.expiresAt
|
|
509
509
|
});
|
|
510
510
|
player.hand.splice(cardIndex, 1);
|
|
511
511
|
targetPile.push(card);
|
|
512
|
-
emitEvent
|
|
512
|
+
emitEvent(game, {
|
|
513
513
|
type: "cardPlayed",
|
|
514
514
|
username: player.username,
|
|
515
515
|
card,
|
|
@@ -517,7 +517,7 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
517
517
|
});
|
|
518
518
|
if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) otherPlayer.hasNoPlayableCards = false;
|
|
519
519
|
if (player.hand.length === 0 && player.drawPile.length === 0) {
|
|
520
|
-
emitEvent
|
|
520
|
+
emitEvent(game, { type: "gameCompleted" });
|
|
521
521
|
return {
|
|
522
522
|
success: true,
|
|
523
523
|
game: {
|
|
@@ -564,7 +564,7 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
564
564
|
error: "canDraw"
|
|
565
565
|
};
|
|
566
566
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
567
|
-
emitEvent
|
|
567
|
+
emitEvent(game, {
|
|
568
568
|
type: "expirationUpdated",
|
|
569
569
|
expiresAt: game.expiresAt
|
|
570
570
|
});
|
|
@@ -575,25 +575,25 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
575
575
|
const cards = [...player.centerPile, ...otherPlayer.centerPile];
|
|
576
576
|
shuffleCards(cards);
|
|
577
577
|
player.sidePile.push(...cards.splice(0, 5));
|
|
578
|
-
emitEvent
|
|
578
|
+
emitEvent(game, {
|
|
579
579
|
type: "playerSidePileInitialized",
|
|
580
580
|
username: player.username,
|
|
581
581
|
numCards: player.sidePile.length
|
|
582
582
|
});
|
|
583
583
|
player.centerPile.push(...cards.splice(0, 1));
|
|
584
|
-
emitEvent
|
|
584
|
+
emitEvent(game, {
|
|
585
585
|
type: "playerCenterPileInitialized",
|
|
586
586
|
username: player.username,
|
|
587
587
|
card: player.centerPile[player.centerPile.length - 1]
|
|
588
588
|
});
|
|
589
589
|
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
590
|
-
emitEvent
|
|
590
|
+
emitEvent(game, {
|
|
591
591
|
type: "playerCenterPileInitialized",
|
|
592
592
|
username: otherPlayer.username,
|
|
593
593
|
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
594
594
|
});
|
|
595
595
|
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
596
|
-
emitEvent
|
|
596
|
+
emitEvent(game, {
|
|
597
597
|
type: "playerSidePileInitialized",
|
|
598
598
|
username: otherPlayer.username,
|
|
599
599
|
numCards: otherPlayer.sidePile.length
|
|
@@ -601,14 +601,14 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
601
601
|
} else {
|
|
602
602
|
const playerSidePileCard = player.sidePile.pop();
|
|
603
603
|
player.centerPile.push(playerSidePileCard);
|
|
604
|
-
emitEvent
|
|
604
|
+
emitEvent(game, {
|
|
605
605
|
type: "cardDrawnFromSidePileToCenterPile",
|
|
606
606
|
username: player.username,
|
|
607
607
|
card: playerSidePileCard
|
|
608
608
|
});
|
|
609
609
|
const otherPlayerSidePileCard = otherPlayer.sidePile.pop();
|
|
610
610
|
otherPlayer.centerPile.push(otherPlayerSidePileCard);
|
|
611
|
-
emitEvent
|
|
611
|
+
emitEvent(game, {
|
|
612
612
|
type: "cardDrawnFromSidePileToCenterPile",
|
|
613
613
|
username: otherPlayer.username,
|
|
614
614
|
card: otherPlayerSidePileCard
|
|
@@ -617,7 +617,7 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
617
617
|
player.hasNoPlayableCards = false;
|
|
618
618
|
otherPlayer.hasNoPlayableCards = false;
|
|
619
619
|
game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;
|
|
620
|
-
emitEvent
|
|
620
|
+
emitEvent(game, {
|
|
621
621
|
type: "canPlayAtUpdated",
|
|
622
622
|
canPlayAt: game.canPlayAt
|
|
623
623
|
});
|
|
@@ -628,32 +628,6 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
628
628
|
};
|
|
629
629
|
}
|
|
630
630
|
//#endregion
|
|
631
|
-
//#region src/game/actions/sendChat.ts
|
|
632
|
-
function sendChat(game, playerId, text) {
|
|
633
|
-
const player = game.players.find((p) => p.id === playerId);
|
|
634
|
-
if (!player) return {
|
|
635
|
-
success: false,
|
|
636
|
-
error: "playerNotFound"
|
|
637
|
-
};
|
|
638
|
-
const message = {
|
|
639
|
-
id: crypto.randomUUID(),
|
|
640
|
-
username: player.username,
|
|
641
|
-
text
|
|
642
|
-
};
|
|
643
|
-
game = {
|
|
644
|
-
...game,
|
|
645
|
-
chatMessages: (0, _hellacardgames_lib.addItemToCollection)(game.chatMessages, message)
|
|
646
|
-
};
|
|
647
|
-
game = (0, _hellacardgames_lib.emitEvent)(game, {
|
|
648
|
-
type: "chat",
|
|
649
|
-
message
|
|
650
|
-
});
|
|
651
|
-
return {
|
|
652
|
-
success: true,
|
|
653
|
-
game
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
//#endregion
|
|
657
631
|
//#region src/game/actions/startGame.ts
|
|
658
632
|
function startGame(game, playerId) {
|
|
659
633
|
const player = game.players.find((p) => p.id === playerId);
|
|
@@ -673,31 +647,31 @@ function startGame(game, playerId) {
|
|
|
673
647
|
const cards = [...CARDS];
|
|
674
648
|
shuffleCards(cards);
|
|
675
649
|
player.sidePile.push(...cards.splice(0, 5));
|
|
676
|
-
emitEvent
|
|
650
|
+
emitEvent(game, {
|
|
677
651
|
type: "playerSidePileInitialized",
|
|
678
652
|
username: player.username,
|
|
679
653
|
numCards: player.sidePile.length
|
|
680
654
|
});
|
|
681
655
|
player.centerPile.push(...cards.splice(0, 1));
|
|
682
|
-
emitEvent
|
|
656
|
+
emitEvent(game, {
|
|
683
657
|
type: "playerCenterPileInitialized",
|
|
684
658
|
username: player.username,
|
|
685
659
|
card: player.centerPile[player.centerPile.length - 1]
|
|
686
660
|
});
|
|
687
661
|
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
688
|
-
emitEvent
|
|
662
|
+
emitEvent(game, {
|
|
689
663
|
type: "playerCenterPileInitialized",
|
|
690
664
|
username: otherPlayer.username,
|
|
691
665
|
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
692
666
|
});
|
|
693
667
|
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
694
|
-
emitEvent
|
|
668
|
+
emitEvent(game, {
|
|
695
669
|
type: "playerSidePileInitialized",
|
|
696
670
|
username: otherPlayer.username,
|
|
697
671
|
numCards: otherPlayer.sidePile.length
|
|
698
672
|
});
|
|
699
673
|
player.drawPile.push(...cards.splice(0, 15));
|
|
700
|
-
emitEvent
|
|
674
|
+
emitEvent(game, {
|
|
701
675
|
type: "playerDrawPileInitialized",
|
|
702
676
|
username: player.username,
|
|
703
677
|
numCards: player.drawPile.length
|
|
@@ -707,13 +681,13 @@ function startGame(game, playerId) {
|
|
|
707
681
|
type: "handInitialized",
|
|
708
682
|
cards: player.hand
|
|
709
683
|
});
|
|
710
|
-
emitEvent
|
|
684
|
+
emitEvent(game, {
|
|
711
685
|
type: "playerHandInitialized",
|
|
712
686
|
username: player.username,
|
|
713
687
|
numCards: player.hand.length
|
|
714
688
|
});
|
|
715
689
|
otherPlayer.drawPile.push(...cards.splice(0, 15));
|
|
716
|
-
emitEvent
|
|
690
|
+
emitEvent(game, {
|
|
717
691
|
type: "playerDrawPileInitialized",
|
|
718
692
|
username: otherPlayer.username,
|
|
719
693
|
numCards: otherPlayer.drawPile.length
|
|
@@ -723,7 +697,7 @@ function startGame(game, playerId) {
|
|
|
723
697
|
type: "handInitialized",
|
|
724
698
|
cards: otherPlayer.hand
|
|
725
699
|
});
|
|
726
|
-
emitEvent
|
|
700
|
+
emitEvent(game, {
|
|
727
701
|
type: "playerHandInitialized",
|
|
728
702
|
username: otherPlayer.username,
|
|
729
703
|
numCards: otherPlayer.hand.length
|
|
@@ -734,12 +708,12 @@ function startGame(game, playerId) {
|
|
|
734
708
|
expiresAt: Date.now() + EXPIRY_EXTENSION_MS,
|
|
735
709
|
canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS
|
|
736
710
|
};
|
|
737
|
-
emitEvent
|
|
738
|
-
emitEvent
|
|
711
|
+
emitEvent(startedGame, { type: "gameStarted" });
|
|
712
|
+
emitEvent(startedGame, {
|
|
739
713
|
type: "expirationUpdated",
|
|
740
714
|
expiresAt: startedGame.expiresAt
|
|
741
715
|
});
|
|
742
|
-
emitEvent
|
|
716
|
+
emitEvent(startedGame, {
|
|
743
717
|
type: "canPlayAtUpdated",
|
|
744
718
|
canPlayAt: startedGame.canPlayAt
|
|
745
719
|
});
|
|
@@ -757,7 +731,6 @@ const createManager = (0, _hellacardgames_lib.createManagerFactory)({
|
|
|
757
731
|
getEventsAndClearAcknowledged,
|
|
758
732
|
joinGame,
|
|
759
733
|
leaveGame,
|
|
760
|
-
sendChat,
|
|
761
734
|
startGame,
|
|
762
735
|
createCustomActions: (games) => ({
|
|
763
736
|
drawCard: (gameId, playerId) => {
|
|
@@ -824,4 +797,4 @@ Object.defineProperty(exports, "createManager", {
|
|
|
824
797
|
}
|
|
825
798
|
});
|
|
826
799
|
|
|
827
|
-
//# sourceMappingURL=manager-
|
|
800
|
+
//# sourceMappingURL=manager-49xVpBPl.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager-49xVpBPl.cjs","names":["doGetEventsAndClearAcknowledged","createManagerFactory"],"sources":["../src/game/constants.ts","../src/game/actions/createGame.ts","../src/game/lib/emitEvent.ts","../src/game/lib/emitEventToPlayer.ts","../src/game/actions/drawCard.ts","../src/game/actions/getClientStateAndClearEvents.ts","../src/game/actions/getEventsAndClearAcknowledged.ts","../src/game/actions/joinGame.ts","../src/game/actions/leaveGame.ts","../src/game/lib/isCardPlayable.ts","../src/game/lib/hasPlayableCard.ts","../src/game/actions/playCard.ts","../src/game/lib/shuffleCards.ts","../src/game/actions/reportNoPlayableCards.ts","../src/game/actions/startGame.ts","../src/manager/createManager.ts"],"sourcesContent":["import type { Card } from \"./types/Card.js\";\n\nexport const EXPIRY_EXTENSION_MS = 300000; // 5 minutes\nexport const MIN_PLAYERS = 2;\nexport const MAX_PLAYERS = 2;\nexport const MAX_HAND_SIZE = 5;\nexport const CAN_PLAY_AT_DELAY_MS = 3000;\n\nexport const CARDS: readonly Card[] = [\n { id: crypto.randomUUID(), rank: 2, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"spades\" },\n];\n","import { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function createGame(userId: string, username: string) {\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n\n const createdAt = Date.now();\n\n const game: CreatedGame = {\n status: \"created\",\n id: crypto.randomUUID(),\n createdAt,\n expiresAt: createdAt + EXPIRY_EXTENSION_MS,\n chatMessages: [],\n players: [player],\n };\n\n return { game, playerId: player.id } as const;\n}\n","type Game = {\n readonly players: {\n readonly events: { readonly id: string }[];\n }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEvent<T extends Game>(\n game: T,\n data: OmitId<T[\"players\"][number][\"events\"][number]>,\n): void {\n const event = { ...data, id: crypto.randomUUID() };\n for (const p of game.players) {\n p.events.push(event);\n }\n}\n","type Player = {\n readonly events: { readonly id: string }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEventToPlayer<T extends Player>(\n player: T,\n data: OmitId<T[\"events\"][number]>,\n): void {\n player.events.push({ ...data, id: crypto.randomUUID() });\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { EXPIRY_EXTENSION_MS, MAX_HAND_SIZE } from \"../constants.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function drawCard(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hand.length >= MAX_HAND_SIZE) {\n return { success: false, error: \"handFull\" } as const;\n }\n if (player.drawPile.length === 0) {\n return { success: false, error: \"drawPileEmpty\" } as const;\n }\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n const card = player.drawPile.pop()!;\n player.hand.push(card);\n emitEventToPlayer(player, { type: \"drewCard\", card });\n emitEvent(game, { type: \"playerDrewCard\", username: player.username });\n return { success: true, game } as const;\n}\n","import type { ClientState } from \"../types/ClientState.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getClientStateAndClearEvents(game: Game, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n const state: ClientState = {\n status: game.status,\n gameId: game.id,\n playerId,\n username: player.username,\n players: game.players.map((p) => ({\n username: p.username,\n handSize: p.hand.length,\n drawPileSize: p.drawPile.length,\n sidePileSize: p.sidePile.length,\n centerPileTopCard: p.centerPile.length\n ? p.centerPile[p.centerPile.length - 1]!\n : null,\n })),\n expiresAt: game.expiresAt,\n chatMessages: game.chatMessages,\n hand: player.hand,\n canPlayAt: game.status === \"started\" ? game.canPlayAt : null,\n };\n player.events.length = 0;\n return { success: true, state, game } as const;\n}\n","import { getEventsAndClearAcknowledged as doGetEventsAndClearAcknowledged } from \"@hellacardgames/lib\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getEventsAndClearAcknowledged(\n game: Game,\n playerId: string,\n lastReadId: string | null,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const result = doGetEventsAndClearAcknowledged(game, player.id, lastReadId);\n\n return {\n success: true,\n events: result.events,\n game: result.game,\n } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { MAX_PLAYERS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function joinGame(game: CreatedGame, userId: string, username: string) {\n if (game.players.length === MAX_PLAYERS) {\n return { success: false, error: \"maxPlayersReached\" } as const;\n }\n if (game.players.find((p) => p.userId === userId)) {\n return { success: false, error: \"alreadyInGame\" } as const;\n }\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n game.players.push(player);\n emitEvent(game, { type: \"playerJoined\", username });\n return { success: true, game, playerId: player.id } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS, MIN_PLAYERS } from \"../constants.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function leaveGame(game: Game, playerId: string) {\n const playerIndex = game.players.findIndex((p) => p.id === playerId);\n if (playerIndex === -1) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const player = game.players[playerIndex]!;\n emitEvent(game, { type: \"playerLeft\", username: player.username });\n\n game.players.splice(playerIndex, 1);\n\n if (game.status === \"started\" && game.players.length < MIN_PLAYERS) {\n const forfeitedGame: Game = {\n ...game,\n status: \"forfeited\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n };\n // this.games.set(game.id, forfeitedGame);\n emitEvent(forfeitedGame, { type: \"gameForfeited\" });\n emitEvent(forfeitedGame, {\n type: \"expirationUpdated\",\n expiresAt: forfeitedGame.expiresAt,\n });\n return { success: true, game: forfeitedGame } as const;\n }\n return { success: true, game } as const;\n}\n","import type { Card } from \"../types/Card.js\";\n\nexport function isCardPlayable(card: Card, targetPile: Card[]) {\n const targetCard = targetPile[targetPile.length - 1]!;\n const diff = Math.abs(card.rank - targetCard.rank) % 11;\n return diff === 1;\n}\n","import { isCardPlayable } from \"./isCardPlayable.js\";\nimport type { Game } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function hasPlayableCard(player: Player, game: Game) {\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile1 = player.centerPile;\n const targetPile2 = otherPlayer.centerPile;\n for (const card of player.hand) {\n if (\n isCardPlayable(card, targetPile1) ||\n isCardPlayable(card, targetPile2)\n ) {\n return true;\n }\n }\n return false;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport { isCardPlayable } from \"../lib/isCardPlayable.js\";\nimport type { CompletedGame, StartedGame } from \"../types/Game.js\";\n\nexport function playCard(\n game: StartedGame,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n const cardIndex = player.hand.findIndex((c) => c.id === cardId);\n if (cardIndex === -1) {\n return { success: false, error: \"cardNotFound\" } as const;\n }\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile = isForOtherPlayerPile\n ? otherPlayer.centerPile\n : player.centerPile;\n const card = player.hand[cardIndex]!;\n if (!isCardPlayable(card, targetPile)) {\n return { success: false, error: \"cardNotPlayable\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hand.splice(cardIndex, 1);\n targetPile.push(card);\n emitEvent(game, {\n type: \"cardPlayed\",\n username: player.username,\n card,\n isForOtherPlayerPile,\n });\n\n if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) {\n otherPlayer.hasNoPlayableCards = false;\n }\n\n if (player.hand.length === 0 && player.drawPile.length === 0) {\n emitEvent(game, { type: \"gameCompleted\" });\n const completedGame: CompletedGame = {\n ...game,\n status: \"completed\",\n };\n return { success: true, game: completedGame } as const;\n }\n\n return { success: true, game } as const;\n}\n","type Card = { readonly id: string };\n\nexport function shuffleCards<T extends Card>(cards: T[]): void {\n for (let i = cards.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [cards[i], cards[j]] = [cards[j]!, cards[i]!];\n }\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n EXPIRY_EXTENSION_MS,\n MAX_HAND_SIZE,\n} from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function reportNoPlayableCards(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hasNoPlayableCards) {\n return { success: false, error: \"alreadyReported\" } as const;\n }\n if (hasPlayableCard(player, game)) {\n return { success: false, error: \"hasPlayableCard\" } as const;\n }\n if (player.drawPile.length > 0 && player.hand.length < MAX_HAND_SIZE) {\n return { success: false, error: \"canDraw\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hasNoPlayableCards = true;\n\n const otherPlayer = game.players.find((p) => p !== player)!;\n if (otherPlayer.hasNoPlayableCards) {\n if (player.sidePile.length === 0 && otherPlayer.sidePile.length === 0) {\n const cards = [...player.centerPile, ...otherPlayer.centerPile];\n shuffleCards(cards);\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n } else {\n const playerSidePileCard = player.sidePile.pop()!;\n player.centerPile.push(playerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: player.username,\n card: playerSidePileCard,\n });\n const otherPlayerSidePileCard = otherPlayer.sidePile.pop()!;\n otherPlayer.centerPile.push(otherPlayerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: otherPlayer.username,\n card: otherPlayerSidePileCard,\n });\n }\n player.hasNoPlayableCards = false;\n otherPlayer.hasNoPlayableCards = false;\n game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;\n emitEvent(game, {\n type: \"canPlayAtUpdated\",\n canPlayAt: game.canPlayAt,\n });\n }\n\n return { success: true, game } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n CARDS,\n EXPIRY_EXTENSION_MS,\n MIN_PLAYERS,\n} from \"../constants.js\";\nimport type { CreatedGame, StartedGame } from \"../types/Game.js\";\n\nexport function startGame(game: CreatedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (game.players.indexOf(player) !== 0) {\n return { success: false, error: \"playerNotAdmin\" } as const;\n }\n if (game.players.length < MIN_PLAYERS) {\n return { success: false, error: \"minPlayersNotReached\" } as const;\n }\n const otherPlayer = game.players[1]!;\n const cards = [...CARDS];\n shuffleCards(cards);\n\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n\n player.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: player.username,\n numCards: player.drawPile.length,\n });\n\n player.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(player, { type: \"handInitialized\", cards: player.hand });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: player.username,\n numCards: player.hand.length,\n });\n\n otherPlayer.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.drawPile.length,\n });\n\n otherPlayer.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(otherPlayer, {\n type: \"handInitialized\",\n cards: otherPlayer.hand,\n });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.hand.length,\n });\n\n const startedGame: StartedGame = {\n ...game,\n status: \"started\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS,\n };\n // this.games.set(game.id, startedGame);\n emitEvent(startedGame, { type: \"gameStarted\" });\n emitEvent(startedGame, {\n type: \"expirationUpdated\",\n expiresAt: startedGame.expiresAt,\n });\n emitEvent(startedGame, {\n type: \"canPlayAtUpdated\",\n canPlayAt: startedGame.canPlayAt,\n });\n return { success: true, game: startedGame } as const;\n}\n","import { createManagerFactory } from \"@hellacardgames/lib\";\nimport {\n createGame,\n drawCard,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n MAX_PLAYERS,\n playCard,\n reportNoPlayableCards,\n startGame,\n} from \"../game/index.js\";\n\nexport const createManager = createManagerFactory({\n maxPlayers: MAX_PLAYERS,\n createGame,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n startGame,\n createCustomActions: (games) => ({\n drawCard: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = drawCard(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n playCard: (\n gameId: string,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n ) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = playCard(game, playerId, cardId, isForOtherPlayerPile);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n reportNoPlayableCards: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = reportNoPlayableCards(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n }),\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createManagerFactory, getEventsAndClearAcknowledged } from "@hellacardgames/lib";
|
|
2
2
|
//#region src/game/constants.ts
|
|
3
3
|
const EXPIRY_EXTENSION_MS = 3e5;
|
|
4
4
|
const CAN_PLAY_AT_DELAY_MS = 3e3;
|
|
@@ -293,7 +293,7 @@ function createGame(userId, username) {
|
|
|
293
293
|
}
|
|
294
294
|
//#endregion
|
|
295
295
|
//#region src/game/lib/emitEvent.ts
|
|
296
|
-
function emitEvent
|
|
296
|
+
function emitEvent(game, data) {
|
|
297
297
|
const event = {
|
|
298
298
|
...data,
|
|
299
299
|
id: crypto.randomUUID()
|
|
@@ -329,7 +329,7 @@ function drawCard(game, playerId) {
|
|
|
329
329
|
error: "drawPileEmpty"
|
|
330
330
|
};
|
|
331
331
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
332
|
-
emitEvent
|
|
332
|
+
emitEvent(game, {
|
|
333
333
|
type: "expirationUpdated",
|
|
334
334
|
expiresAt: game.expiresAt
|
|
335
335
|
});
|
|
@@ -339,7 +339,7 @@ function drawCard(game, playerId) {
|
|
|
339
339
|
type: "drewCard",
|
|
340
340
|
card
|
|
341
341
|
});
|
|
342
|
-
emitEvent
|
|
342
|
+
emitEvent(game, {
|
|
343
343
|
type: "playerDrewCard",
|
|
344
344
|
username: player.username
|
|
345
345
|
});
|
|
@@ -418,7 +418,7 @@ function joinGame(game, userId, username) {
|
|
|
418
418
|
hasNoPlayableCards: false
|
|
419
419
|
};
|
|
420
420
|
game.players.push(player);
|
|
421
|
-
emitEvent
|
|
421
|
+
emitEvent(game, {
|
|
422
422
|
type: "playerJoined",
|
|
423
423
|
username
|
|
424
424
|
});
|
|
@@ -437,7 +437,7 @@ function leaveGame(game, playerId) {
|
|
|
437
437
|
error: "playerNotFound"
|
|
438
438
|
};
|
|
439
439
|
const player = game.players[playerIndex];
|
|
440
|
-
emitEvent
|
|
440
|
+
emitEvent(game, {
|
|
441
441
|
type: "playerLeft",
|
|
442
442
|
username: player.username
|
|
443
443
|
});
|
|
@@ -448,8 +448,8 @@ function leaveGame(game, playerId) {
|
|
|
448
448
|
status: "forfeited",
|
|
449
449
|
expiresAt: Date.now() + EXPIRY_EXTENSION_MS
|
|
450
450
|
};
|
|
451
|
-
emitEvent
|
|
452
|
-
emitEvent
|
|
451
|
+
emitEvent(forfeitedGame, { type: "gameForfeited" });
|
|
452
|
+
emitEvent(forfeitedGame, {
|
|
453
453
|
type: "expirationUpdated",
|
|
454
454
|
expiresAt: forfeitedGame.expiresAt
|
|
455
455
|
});
|
|
@@ -503,13 +503,13 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
503
503
|
error: "cardNotPlayable"
|
|
504
504
|
};
|
|
505
505
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
506
|
-
emitEvent
|
|
506
|
+
emitEvent(game, {
|
|
507
507
|
type: "expirationUpdated",
|
|
508
508
|
expiresAt: game.expiresAt
|
|
509
509
|
});
|
|
510
510
|
player.hand.splice(cardIndex, 1);
|
|
511
511
|
targetPile.push(card);
|
|
512
|
-
emitEvent
|
|
512
|
+
emitEvent(game, {
|
|
513
513
|
type: "cardPlayed",
|
|
514
514
|
username: player.username,
|
|
515
515
|
card,
|
|
@@ -517,7 +517,7 @@ function playCard(game, playerId, cardId, isForOtherPlayerPile) {
|
|
|
517
517
|
});
|
|
518
518
|
if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) otherPlayer.hasNoPlayableCards = false;
|
|
519
519
|
if (player.hand.length === 0 && player.drawPile.length === 0) {
|
|
520
|
-
emitEvent
|
|
520
|
+
emitEvent(game, { type: "gameCompleted" });
|
|
521
521
|
return {
|
|
522
522
|
success: true,
|
|
523
523
|
game: {
|
|
@@ -564,7 +564,7 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
564
564
|
error: "canDraw"
|
|
565
565
|
};
|
|
566
566
|
game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;
|
|
567
|
-
emitEvent
|
|
567
|
+
emitEvent(game, {
|
|
568
568
|
type: "expirationUpdated",
|
|
569
569
|
expiresAt: game.expiresAt
|
|
570
570
|
});
|
|
@@ -575,25 +575,25 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
575
575
|
const cards = [...player.centerPile, ...otherPlayer.centerPile];
|
|
576
576
|
shuffleCards(cards);
|
|
577
577
|
player.sidePile.push(...cards.splice(0, 5));
|
|
578
|
-
emitEvent
|
|
578
|
+
emitEvent(game, {
|
|
579
579
|
type: "playerSidePileInitialized",
|
|
580
580
|
username: player.username,
|
|
581
581
|
numCards: player.sidePile.length
|
|
582
582
|
});
|
|
583
583
|
player.centerPile.push(...cards.splice(0, 1));
|
|
584
|
-
emitEvent
|
|
584
|
+
emitEvent(game, {
|
|
585
585
|
type: "playerCenterPileInitialized",
|
|
586
586
|
username: player.username,
|
|
587
587
|
card: player.centerPile[player.centerPile.length - 1]
|
|
588
588
|
});
|
|
589
589
|
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
590
|
-
emitEvent
|
|
590
|
+
emitEvent(game, {
|
|
591
591
|
type: "playerCenterPileInitialized",
|
|
592
592
|
username: otherPlayer.username,
|
|
593
593
|
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
594
594
|
});
|
|
595
595
|
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
596
|
-
emitEvent
|
|
596
|
+
emitEvent(game, {
|
|
597
597
|
type: "playerSidePileInitialized",
|
|
598
598
|
username: otherPlayer.username,
|
|
599
599
|
numCards: otherPlayer.sidePile.length
|
|
@@ -601,14 +601,14 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
601
601
|
} else {
|
|
602
602
|
const playerSidePileCard = player.sidePile.pop();
|
|
603
603
|
player.centerPile.push(playerSidePileCard);
|
|
604
|
-
emitEvent
|
|
604
|
+
emitEvent(game, {
|
|
605
605
|
type: "cardDrawnFromSidePileToCenterPile",
|
|
606
606
|
username: player.username,
|
|
607
607
|
card: playerSidePileCard
|
|
608
608
|
});
|
|
609
609
|
const otherPlayerSidePileCard = otherPlayer.sidePile.pop();
|
|
610
610
|
otherPlayer.centerPile.push(otherPlayerSidePileCard);
|
|
611
|
-
emitEvent
|
|
611
|
+
emitEvent(game, {
|
|
612
612
|
type: "cardDrawnFromSidePileToCenterPile",
|
|
613
613
|
username: otherPlayer.username,
|
|
614
614
|
card: otherPlayerSidePileCard
|
|
@@ -617,7 +617,7 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
617
617
|
player.hasNoPlayableCards = false;
|
|
618
618
|
otherPlayer.hasNoPlayableCards = false;
|
|
619
619
|
game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;
|
|
620
|
-
emitEvent
|
|
620
|
+
emitEvent(game, {
|
|
621
621
|
type: "canPlayAtUpdated",
|
|
622
622
|
canPlayAt: game.canPlayAt
|
|
623
623
|
});
|
|
@@ -628,32 +628,6 @@ function reportNoPlayableCards(game, playerId) {
|
|
|
628
628
|
};
|
|
629
629
|
}
|
|
630
630
|
//#endregion
|
|
631
|
-
//#region src/game/actions/sendChat.ts
|
|
632
|
-
function sendChat(game, playerId, text) {
|
|
633
|
-
const player = game.players.find((p) => p.id === playerId);
|
|
634
|
-
if (!player) return {
|
|
635
|
-
success: false,
|
|
636
|
-
error: "playerNotFound"
|
|
637
|
-
};
|
|
638
|
-
const message = {
|
|
639
|
-
id: crypto.randomUUID(),
|
|
640
|
-
username: player.username,
|
|
641
|
-
text
|
|
642
|
-
};
|
|
643
|
-
game = {
|
|
644
|
-
...game,
|
|
645
|
-
chatMessages: addItemToCollection(game.chatMessages, message)
|
|
646
|
-
};
|
|
647
|
-
game = emitEvent(game, {
|
|
648
|
-
type: "chat",
|
|
649
|
-
message
|
|
650
|
-
});
|
|
651
|
-
return {
|
|
652
|
-
success: true,
|
|
653
|
-
game
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
//#endregion
|
|
657
631
|
//#region src/game/actions/startGame.ts
|
|
658
632
|
function startGame(game, playerId) {
|
|
659
633
|
const player = game.players.find((p) => p.id === playerId);
|
|
@@ -673,31 +647,31 @@ function startGame(game, playerId) {
|
|
|
673
647
|
const cards = [...CARDS];
|
|
674
648
|
shuffleCards(cards);
|
|
675
649
|
player.sidePile.push(...cards.splice(0, 5));
|
|
676
|
-
emitEvent
|
|
650
|
+
emitEvent(game, {
|
|
677
651
|
type: "playerSidePileInitialized",
|
|
678
652
|
username: player.username,
|
|
679
653
|
numCards: player.sidePile.length
|
|
680
654
|
});
|
|
681
655
|
player.centerPile.push(...cards.splice(0, 1));
|
|
682
|
-
emitEvent
|
|
656
|
+
emitEvent(game, {
|
|
683
657
|
type: "playerCenterPileInitialized",
|
|
684
658
|
username: player.username,
|
|
685
659
|
card: player.centerPile[player.centerPile.length - 1]
|
|
686
660
|
});
|
|
687
661
|
otherPlayer.centerPile.push(...cards.splice(0, 1));
|
|
688
|
-
emitEvent
|
|
662
|
+
emitEvent(game, {
|
|
689
663
|
type: "playerCenterPileInitialized",
|
|
690
664
|
username: otherPlayer.username,
|
|
691
665
|
card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]
|
|
692
666
|
});
|
|
693
667
|
otherPlayer.sidePile.push(...cards.splice(0, 5));
|
|
694
|
-
emitEvent
|
|
668
|
+
emitEvent(game, {
|
|
695
669
|
type: "playerSidePileInitialized",
|
|
696
670
|
username: otherPlayer.username,
|
|
697
671
|
numCards: otherPlayer.sidePile.length
|
|
698
672
|
});
|
|
699
673
|
player.drawPile.push(...cards.splice(0, 15));
|
|
700
|
-
emitEvent
|
|
674
|
+
emitEvent(game, {
|
|
701
675
|
type: "playerDrawPileInitialized",
|
|
702
676
|
username: player.username,
|
|
703
677
|
numCards: player.drawPile.length
|
|
@@ -707,13 +681,13 @@ function startGame(game, playerId) {
|
|
|
707
681
|
type: "handInitialized",
|
|
708
682
|
cards: player.hand
|
|
709
683
|
});
|
|
710
|
-
emitEvent
|
|
684
|
+
emitEvent(game, {
|
|
711
685
|
type: "playerHandInitialized",
|
|
712
686
|
username: player.username,
|
|
713
687
|
numCards: player.hand.length
|
|
714
688
|
});
|
|
715
689
|
otherPlayer.drawPile.push(...cards.splice(0, 15));
|
|
716
|
-
emitEvent
|
|
690
|
+
emitEvent(game, {
|
|
717
691
|
type: "playerDrawPileInitialized",
|
|
718
692
|
username: otherPlayer.username,
|
|
719
693
|
numCards: otherPlayer.drawPile.length
|
|
@@ -723,7 +697,7 @@ function startGame(game, playerId) {
|
|
|
723
697
|
type: "handInitialized",
|
|
724
698
|
cards: otherPlayer.hand
|
|
725
699
|
});
|
|
726
|
-
emitEvent
|
|
700
|
+
emitEvent(game, {
|
|
727
701
|
type: "playerHandInitialized",
|
|
728
702
|
username: otherPlayer.username,
|
|
729
703
|
numCards: otherPlayer.hand.length
|
|
@@ -734,12 +708,12 @@ function startGame(game, playerId) {
|
|
|
734
708
|
expiresAt: Date.now() + EXPIRY_EXTENSION_MS,
|
|
735
709
|
canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS
|
|
736
710
|
};
|
|
737
|
-
emitEvent
|
|
738
|
-
emitEvent
|
|
711
|
+
emitEvent(startedGame, { type: "gameStarted" });
|
|
712
|
+
emitEvent(startedGame, {
|
|
739
713
|
type: "expirationUpdated",
|
|
740
714
|
expiresAt: startedGame.expiresAt
|
|
741
715
|
});
|
|
742
|
-
emitEvent
|
|
716
|
+
emitEvent(startedGame, {
|
|
743
717
|
type: "canPlayAtUpdated",
|
|
744
718
|
canPlayAt: startedGame.canPlayAt
|
|
745
719
|
});
|
|
@@ -757,7 +731,6 @@ const createManager = createManagerFactory({
|
|
|
757
731
|
getEventsAndClearAcknowledged: getEventsAndClearAcknowledged$1,
|
|
758
732
|
joinGame,
|
|
759
733
|
leaveGame,
|
|
760
|
-
sendChat,
|
|
761
734
|
startGame,
|
|
762
735
|
createCustomActions: (games) => ({
|
|
763
736
|
drawCard: (gameId, playerId) => {
|
|
@@ -819,4 +792,4 @@ const createManager = createManagerFactory({
|
|
|
819
792
|
//#endregion
|
|
820
793
|
export { createManager as t };
|
|
821
794
|
|
|
822
|
-
//# sourceMappingURL=manager-
|
|
795
|
+
//# sourceMappingURL=manager-BYLO6oGT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager-BYLO6oGT.mjs","names":["getEventsAndClearAcknowledged","doGetEventsAndClearAcknowledged"],"sources":["../src/game/constants.ts","../src/game/actions/createGame.ts","../src/game/lib/emitEvent.ts","../src/game/lib/emitEventToPlayer.ts","../src/game/actions/drawCard.ts","../src/game/actions/getClientStateAndClearEvents.ts","../src/game/actions/getEventsAndClearAcknowledged.ts","../src/game/actions/joinGame.ts","../src/game/actions/leaveGame.ts","../src/game/lib/isCardPlayable.ts","../src/game/lib/hasPlayableCard.ts","../src/game/actions/playCard.ts","../src/game/lib/shuffleCards.ts","../src/game/actions/reportNoPlayableCards.ts","../src/game/actions/startGame.ts","../src/manager/createManager.ts"],"sourcesContent":["import type { Card } from \"./types/Card.js\";\n\nexport const EXPIRY_EXTENSION_MS = 300000; // 5 minutes\nexport const MIN_PLAYERS = 2;\nexport const MAX_PLAYERS = 2;\nexport const MAX_HAND_SIZE = 5;\nexport const CAN_PLAY_AT_DELAY_MS = 3000;\n\nexport const CARDS: readonly Card[] = [\n { id: crypto.randomUUID(), rank: 2, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"spades\" },\n];\n","import { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function createGame(userId: string, username: string) {\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n\n const createdAt = Date.now();\n\n const game: CreatedGame = {\n status: \"created\",\n id: crypto.randomUUID(),\n createdAt,\n expiresAt: createdAt + EXPIRY_EXTENSION_MS,\n chatMessages: [],\n players: [player],\n };\n\n return { game, playerId: player.id } as const;\n}\n","type Game = {\n readonly players: {\n readonly events: { readonly id: string }[];\n }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEvent<T extends Game>(\n game: T,\n data: OmitId<T[\"players\"][number][\"events\"][number]>,\n): void {\n const event = { ...data, id: crypto.randomUUID() };\n for (const p of game.players) {\n p.events.push(event);\n }\n}\n","type Player = {\n readonly events: { readonly id: string }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEventToPlayer<T extends Player>(\n player: T,\n data: OmitId<T[\"events\"][number]>,\n): void {\n player.events.push({ ...data, id: crypto.randomUUID() });\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { EXPIRY_EXTENSION_MS, MAX_HAND_SIZE } from \"../constants.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function drawCard(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hand.length >= MAX_HAND_SIZE) {\n return { success: false, error: \"handFull\" } as const;\n }\n if (player.drawPile.length === 0) {\n return { success: false, error: \"drawPileEmpty\" } as const;\n }\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n const card = player.drawPile.pop()!;\n player.hand.push(card);\n emitEventToPlayer(player, { type: \"drewCard\", card });\n emitEvent(game, { type: \"playerDrewCard\", username: player.username });\n return { success: true, game } as const;\n}\n","import type { ClientState } from \"../types/ClientState.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getClientStateAndClearEvents(game: Game, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n const state: ClientState = {\n status: game.status,\n gameId: game.id,\n playerId,\n username: player.username,\n players: game.players.map((p) => ({\n username: p.username,\n handSize: p.hand.length,\n drawPileSize: p.drawPile.length,\n sidePileSize: p.sidePile.length,\n centerPileTopCard: p.centerPile.length\n ? p.centerPile[p.centerPile.length - 1]!\n : null,\n })),\n expiresAt: game.expiresAt,\n chatMessages: game.chatMessages,\n hand: player.hand,\n canPlayAt: game.status === \"started\" ? game.canPlayAt : null,\n };\n player.events.length = 0;\n return { success: true, state, game } as const;\n}\n","import { getEventsAndClearAcknowledged as doGetEventsAndClearAcknowledged } from \"@hellacardgames/lib\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getEventsAndClearAcknowledged(\n game: Game,\n playerId: string,\n lastReadId: string | null,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const result = doGetEventsAndClearAcknowledged(game, player.id, lastReadId);\n\n return {\n success: true,\n events: result.events,\n game: result.game,\n } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { MAX_PLAYERS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function joinGame(game: CreatedGame, userId: string, username: string) {\n if (game.players.length === MAX_PLAYERS) {\n return { success: false, error: \"maxPlayersReached\" } as const;\n }\n if (game.players.find((p) => p.userId === userId)) {\n return { success: false, error: \"alreadyInGame\" } as const;\n }\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n game.players.push(player);\n emitEvent(game, { type: \"playerJoined\", username });\n return { success: true, game, playerId: player.id } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS, MIN_PLAYERS } from \"../constants.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function leaveGame(game: Game, playerId: string) {\n const playerIndex = game.players.findIndex((p) => p.id === playerId);\n if (playerIndex === -1) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const player = game.players[playerIndex]!;\n emitEvent(game, { type: \"playerLeft\", username: player.username });\n\n game.players.splice(playerIndex, 1);\n\n if (game.status === \"started\" && game.players.length < MIN_PLAYERS) {\n const forfeitedGame: Game = {\n ...game,\n status: \"forfeited\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n };\n // this.games.set(game.id, forfeitedGame);\n emitEvent(forfeitedGame, { type: \"gameForfeited\" });\n emitEvent(forfeitedGame, {\n type: \"expirationUpdated\",\n expiresAt: forfeitedGame.expiresAt,\n });\n return { success: true, game: forfeitedGame } as const;\n }\n return { success: true, game } as const;\n}\n","import type { Card } from \"../types/Card.js\";\n\nexport function isCardPlayable(card: Card, targetPile: Card[]) {\n const targetCard = targetPile[targetPile.length - 1]!;\n const diff = Math.abs(card.rank - targetCard.rank) % 11;\n return diff === 1;\n}\n","import { isCardPlayable } from \"./isCardPlayable.js\";\nimport type { Game } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function hasPlayableCard(player: Player, game: Game) {\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile1 = player.centerPile;\n const targetPile2 = otherPlayer.centerPile;\n for (const card of player.hand) {\n if (\n isCardPlayable(card, targetPile1) ||\n isCardPlayable(card, targetPile2)\n ) {\n return true;\n }\n }\n return false;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport { isCardPlayable } from \"../lib/isCardPlayable.js\";\nimport type { CompletedGame, StartedGame } from \"../types/Game.js\";\n\nexport function playCard(\n game: StartedGame,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n const cardIndex = player.hand.findIndex((c) => c.id === cardId);\n if (cardIndex === -1) {\n return { success: false, error: \"cardNotFound\" } as const;\n }\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile = isForOtherPlayerPile\n ? otherPlayer.centerPile\n : player.centerPile;\n const card = player.hand[cardIndex]!;\n if (!isCardPlayable(card, targetPile)) {\n return { success: false, error: \"cardNotPlayable\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hand.splice(cardIndex, 1);\n targetPile.push(card);\n emitEvent(game, {\n type: \"cardPlayed\",\n username: player.username,\n card,\n isForOtherPlayerPile,\n });\n\n if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) {\n otherPlayer.hasNoPlayableCards = false;\n }\n\n if (player.hand.length === 0 && player.drawPile.length === 0) {\n emitEvent(game, { type: \"gameCompleted\" });\n const completedGame: CompletedGame = {\n ...game,\n status: \"completed\",\n };\n return { success: true, game: completedGame } as const;\n }\n\n return { success: true, game } as const;\n}\n","type Card = { readonly id: string };\n\nexport function shuffleCards<T extends Card>(cards: T[]): void {\n for (let i = cards.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [cards[i], cards[j]] = [cards[j]!, cards[i]!];\n }\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n EXPIRY_EXTENSION_MS,\n MAX_HAND_SIZE,\n} from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function reportNoPlayableCards(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hasNoPlayableCards) {\n return { success: false, error: \"alreadyReported\" } as const;\n }\n if (hasPlayableCard(player, game)) {\n return { success: false, error: \"hasPlayableCard\" } as const;\n }\n if (player.drawPile.length > 0 && player.hand.length < MAX_HAND_SIZE) {\n return { success: false, error: \"canDraw\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hasNoPlayableCards = true;\n\n const otherPlayer = game.players.find((p) => p !== player)!;\n if (otherPlayer.hasNoPlayableCards) {\n if (player.sidePile.length === 0 && otherPlayer.sidePile.length === 0) {\n const cards = [...player.centerPile, ...otherPlayer.centerPile];\n shuffleCards(cards);\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n } else {\n const playerSidePileCard = player.sidePile.pop()!;\n player.centerPile.push(playerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: player.username,\n card: playerSidePileCard,\n });\n const otherPlayerSidePileCard = otherPlayer.sidePile.pop()!;\n otherPlayer.centerPile.push(otherPlayerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: otherPlayer.username,\n card: otherPlayerSidePileCard,\n });\n }\n player.hasNoPlayableCards = false;\n otherPlayer.hasNoPlayableCards = false;\n game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;\n emitEvent(game, {\n type: \"canPlayAtUpdated\",\n canPlayAt: game.canPlayAt,\n });\n }\n\n return { success: true, game } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n CARDS,\n EXPIRY_EXTENSION_MS,\n MIN_PLAYERS,\n} from \"../constants.js\";\nimport type { CreatedGame, StartedGame } from \"../types/Game.js\";\n\nexport function startGame(game: CreatedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (game.players.indexOf(player) !== 0) {\n return { success: false, error: \"playerNotAdmin\" } as const;\n }\n if (game.players.length < MIN_PLAYERS) {\n return { success: false, error: \"minPlayersNotReached\" } as const;\n }\n const otherPlayer = game.players[1]!;\n const cards = [...CARDS];\n shuffleCards(cards);\n\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n\n player.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: player.username,\n numCards: player.drawPile.length,\n });\n\n player.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(player, { type: \"handInitialized\", cards: player.hand });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: player.username,\n numCards: player.hand.length,\n });\n\n otherPlayer.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.drawPile.length,\n });\n\n otherPlayer.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(otherPlayer, {\n type: \"handInitialized\",\n cards: otherPlayer.hand,\n });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.hand.length,\n });\n\n const startedGame: StartedGame = {\n ...game,\n status: \"started\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS,\n };\n // this.games.set(game.id, startedGame);\n emitEvent(startedGame, { type: \"gameStarted\" });\n emitEvent(startedGame, {\n type: \"expirationUpdated\",\n expiresAt: startedGame.expiresAt,\n });\n emitEvent(startedGame, {\n type: \"canPlayAtUpdated\",\n canPlayAt: startedGame.canPlayAt,\n });\n return { success: true, game: startedGame } as const;\n}\n","import { createManagerFactory } from \"@hellacardgames/lib\";\nimport {\n createGame,\n drawCard,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n MAX_PLAYERS,\n playCard,\n reportNoPlayableCards,\n startGame,\n} from \"../game/index.js\";\n\nexport const createManager = createManagerFactory({\n maxPlayers: MAX_PLAYERS,\n createGame,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n startGame,\n createCustomActions: (games) => ({\n drawCard: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = drawCard(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n playCard: (\n gameId: string,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n ) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = playCard(game, playerId, cardId, isForOtherPlayerPile);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n reportNoPlayableCards: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = reportNoPlayableCards(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n }),\n});\n"],"mappings":"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"}
|
package/dist/server/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_manager = require("../manager-
|
|
2
|
+
const require_manager = require("../manager-49xVpBPl.cjs");
|
|
3
3
|
let _hellacardgames_lib = require("@hellacardgames/lib");
|
|
4
4
|
let zod = require("zod");
|
|
5
5
|
//#region src/server/createServer.ts
|
package/dist/server/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as GameEvent, t as ClientState } from "../
|
|
1
|
+
import { n as GameEvent, t as ClientState } from "../index-89KVb2dD.cjs";
|
|
2
2
|
//#region src/server/createServer.d.ts
|
|
3
3
|
declare const createServer: (logKey: string, maxGames: number, watchdogIntervalMs: number) => {
|
|
4
4
|
readonly actions: readonly [{
|
package/dist/server/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as GameEvent, t as ClientState } from "../
|
|
1
|
+
import { n as GameEvent, t as ClientState } from "../index-89KVb2dD.mjs";
|
|
2
2
|
//#region src/server/createServer.d.ts
|
|
3
3
|
declare const createServer: (logKey: string, maxGames: number, watchdogIntervalMs: number) => {
|
|
4
4
|
readonly actions: readonly [{
|
package/dist/server/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hellacardgames/speed",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "A TypeScript library implementing the Speed card game.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"vitest": "^4.1.9"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@hellacardgames/lib": "^0.
|
|
89
|
+
"@hellacardgames/lib": "^0.8.0",
|
|
90
90
|
"zod": "^4.4.3"
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClientState-Dx8UvhMt.d.cts","names":[],"sources":["../src/game/types/Card.ts","../src/game/types/ChatMessage.ts","../src/game/types/GameEvent.ts","../src/game/types/ClientState.ts"],"mappings":";KAAY;WACD;WACA;WACA;;;;KCHC;WACD;WACA;WACA;;;;KCAC;WAEG;WACA;WACA;;WAGA;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA,MAAM;WACN;;WAGA;WACA;WACA,SAAS;;WAGT;WACA;WACA,MAAM;;WAGN;WACA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WACA,gBAAgB;;WAGhB;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;;;KCxFH;WACD;WACA;WACA;WACA;WACA,kBAAkB;WAClB;WACA,uBAAuB;WACvB,eAAe;WACf;;KAGN;WACM;WACA;WACA;WACA;WACA,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ClientState-Dx8UvhMt.d.mts","names":[],"sources":["../src/game/types/Card.ts","../src/game/types/ChatMessage.ts","../src/game/types/GameEvent.ts","../src/game/types/ClientState.ts"],"mappings":";KAAY;WACD;WACA;WACA;;;;KCHC;WACD;WACA;WACA;;;;KCAC;WAEG;WACA;WACA;;WAGA;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA,MAAM;WACN;;WAGA;WACA;WACA,SAAS;;WAGT;WACA;WACA,MAAM;;WAGN;WACA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;;WAGA;WACA;WACA,gBAAgB;;WAGhB;WACA;WACA;WACA,MAAM;;WAGN;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;;WAGA;WACA;WACA;WACA;;;;KCxFH;WACD;WACA;WACA;WACA;WACA,kBAAkB;WAClB;WACA,uBAAuB;WACvB,eAAe;WACf;;KAGN;WACM;WACA;WACA;WACA;WACA,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manager-B7nTzkpn.mjs","names":["emitEvent","getEventsAndClearAcknowledged","doGetEventsAndClearAcknowledged"],"sources":["../src/game/constants.ts","../src/game/actions/createGame.ts","../src/game/lib/emitEvent.ts","../src/game/lib/emitEventToPlayer.ts","../src/game/actions/drawCard.ts","../src/game/actions/getClientStateAndClearEvents.ts","../src/game/actions/getEventsAndClearAcknowledged.ts","../src/game/actions/joinGame.ts","../src/game/actions/leaveGame.ts","../src/game/lib/isCardPlayable.ts","../src/game/lib/hasPlayableCard.ts","../src/game/actions/playCard.ts","../src/game/lib/shuffleCards.ts","../src/game/actions/reportNoPlayableCards.ts","../src/game/actions/sendChat.ts","../src/game/actions/startGame.ts","../src/manager/createManager.ts"],"sourcesContent":["import type { Card } from \"./types/Card.js\";\n\nexport const EXPIRY_EXTENSION_MS = 300000; // 5 minutes\nexport const MIN_PLAYERS = 2;\nexport const MAX_PLAYERS = 2;\nexport const MAX_HAND_SIZE = 5;\nexport const CAN_PLAY_AT_DELAY_MS = 3000;\n\nexport const CARDS: readonly Card[] = [\n { id: crypto.randomUUID(), rank: 2, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"spades\" },\n];\n","import { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function createGame(userId: string, username: string) {\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n\n const createdAt = Date.now();\n\n const game: CreatedGame = {\n status: \"created\",\n id: crypto.randomUUID(),\n createdAt,\n expiresAt: createdAt + EXPIRY_EXTENSION_MS,\n chatMessages: [],\n players: [player],\n };\n\n return { game, playerId: player.id } as const;\n}\n","type Game = {\n readonly players: {\n readonly events: { readonly id: string }[];\n }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEvent<T extends Game>(\n game: T,\n data: OmitId<T[\"players\"][number][\"events\"][number]>,\n): void {\n const event = { ...data, id: crypto.randomUUID() };\n for (const p of game.players) {\n p.events.push(event);\n }\n}\n","type Player = {\n readonly events: { readonly id: string }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEventToPlayer<T extends Player>(\n player: T,\n data: OmitId<T[\"events\"][number]>,\n): void {\n player.events.push({ ...data, id: crypto.randomUUID() });\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { EXPIRY_EXTENSION_MS, MAX_HAND_SIZE } from \"../constants.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function drawCard(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hand.length >= MAX_HAND_SIZE) {\n return { success: false, error: \"handFull\" } as const;\n }\n if (player.drawPile.length === 0) {\n return { success: false, error: \"drawPileEmpty\" } as const;\n }\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n const card = player.drawPile.pop()!;\n player.hand.push(card);\n emitEventToPlayer(player, { type: \"drewCard\", card });\n emitEvent(game, { type: \"playerDrewCard\", username: player.username });\n return { success: true, game } as const;\n}\n","import type { ClientState } from \"../types/ClientState.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getClientStateAndClearEvents(game: Game, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n const state: ClientState = {\n status: game.status,\n gameId: game.id,\n playerId,\n username: player.username,\n players: game.players.map((p) => ({\n username: p.username,\n handSize: p.hand.length,\n drawPileSize: p.drawPile.length,\n sidePileSize: p.sidePile.length,\n centerPileTopCard: p.centerPile.length\n ? p.centerPile[p.centerPile.length - 1]!\n : null,\n })),\n expiresAt: game.expiresAt,\n chatMessages: game.chatMessages,\n hand: player.hand,\n canPlayAt: game.status === \"started\" ? game.canPlayAt : null,\n };\n player.events.length = 0;\n return { success: true, state, game } as const;\n}\n","import { getEventsAndClearAcknowledged as doGetEventsAndClearAcknowledged } from \"@hellacardgames/lib\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getEventsAndClearAcknowledged(\n game: Game,\n playerId: string,\n lastReadId: string | null,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const result = doGetEventsAndClearAcknowledged(game, player.id, lastReadId);\n\n return {\n success: true,\n events: result.events,\n game: result.game,\n } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { MAX_PLAYERS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function joinGame(game: CreatedGame, userId: string, username: string) {\n if (game.players.length === MAX_PLAYERS) {\n return { success: false, error: \"maxPlayersReached\" } as const;\n }\n if (game.players.find((p) => p.userId === userId)) {\n return { success: false, error: \"alreadyInGame\" } as const;\n }\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n game.players.push(player);\n emitEvent(game, { type: \"playerJoined\", username });\n return { success: true, game, playerId: player.id } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS, MIN_PLAYERS } from \"../constants.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function leaveGame(game: Game, playerId: string) {\n const playerIndex = game.players.findIndex((p) => p.id === playerId);\n if (playerIndex === -1) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const player = game.players[playerIndex]!;\n emitEvent(game, { type: \"playerLeft\", username: player.username });\n\n game.players.splice(playerIndex, 1);\n\n if (game.status === \"started\" && game.players.length < MIN_PLAYERS) {\n const forfeitedGame: Game = {\n ...game,\n status: \"forfeited\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n };\n // this.games.set(game.id, forfeitedGame);\n emitEvent(forfeitedGame, { type: \"gameForfeited\" });\n emitEvent(forfeitedGame, {\n type: \"expirationUpdated\",\n expiresAt: forfeitedGame.expiresAt,\n });\n return { success: true, game: forfeitedGame } as const;\n }\n return { success: true, game } as const;\n}\n","import type { Card } from \"../types/Card.js\";\n\nexport function isCardPlayable(card: Card, targetPile: Card[]) {\n const targetCard = targetPile[targetPile.length - 1]!;\n const diff = Math.abs(card.rank - targetCard.rank) % 11;\n return diff === 1;\n}\n","import { isCardPlayable } from \"./isCardPlayable.js\";\nimport type { Game } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function hasPlayableCard(player: Player, game: Game) {\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile1 = player.centerPile;\n const targetPile2 = otherPlayer.centerPile;\n for (const card of player.hand) {\n if (\n isCardPlayable(card, targetPile1) ||\n isCardPlayable(card, targetPile2)\n ) {\n return true;\n }\n }\n return false;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport { isCardPlayable } from \"../lib/isCardPlayable.js\";\nimport type { CompletedGame, StartedGame } from \"../types/Game.js\";\n\nexport function playCard(\n game: StartedGame,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n const cardIndex = player.hand.findIndex((c) => c.id === cardId);\n if (cardIndex === -1) {\n return { success: false, error: \"cardNotFound\" } as const;\n }\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile = isForOtherPlayerPile\n ? otherPlayer.centerPile\n : player.centerPile;\n const card = player.hand[cardIndex]!;\n if (!isCardPlayable(card, targetPile)) {\n return { success: false, error: \"cardNotPlayable\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hand.splice(cardIndex, 1);\n targetPile.push(card);\n emitEvent(game, {\n type: \"cardPlayed\",\n username: player.username,\n card,\n isForOtherPlayerPile,\n });\n\n if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) {\n otherPlayer.hasNoPlayableCards = false;\n }\n\n if (player.hand.length === 0 && player.drawPile.length === 0) {\n emitEvent(game, { type: \"gameCompleted\" });\n const completedGame: CompletedGame = {\n ...game,\n status: \"completed\",\n };\n return { success: true, game: completedGame } as const;\n }\n\n return { success: true, game } as const;\n}\n","type Card = { readonly id: string };\n\nexport function shuffleCards<T extends Card>(cards: T[]): void {\n for (let i = cards.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [cards[i], cards[j]] = [cards[j]!, cards[i]!];\n }\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n EXPIRY_EXTENSION_MS,\n MAX_HAND_SIZE,\n} from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function reportNoPlayableCards(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hasNoPlayableCards) {\n return { success: false, error: \"alreadyReported\" } as const;\n }\n if (hasPlayableCard(player, game)) {\n return { success: false, error: \"hasPlayableCard\" } as const;\n }\n if (player.drawPile.length > 0 && player.hand.length < MAX_HAND_SIZE) {\n return { success: false, error: \"canDraw\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hasNoPlayableCards = true;\n\n const otherPlayer = game.players.find((p) => p !== player)!;\n if (otherPlayer.hasNoPlayableCards) {\n if (player.sidePile.length === 0 && otherPlayer.sidePile.length === 0) {\n const cards = [...player.centerPile, ...otherPlayer.centerPile];\n shuffleCards(cards);\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n } else {\n const playerSidePileCard = player.sidePile.pop()!;\n player.centerPile.push(playerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: player.username,\n card: playerSidePileCard,\n });\n const otherPlayerSidePileCard = otherPlayer.sidePile.pop()!;\n otherPlayer.centerPile.push(otherPlayerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: otherPlayer.username,\n card: otherPlayerSidePileCard,\n });\n }\n player.hasNoPlayableCards = false;\n otherPlayer.hasNoPlayableCards = false;\n game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;\n emitEvent(game, {\n type: \"canPlayAtUpdated\",\n canPlayAt: game.canPlayAt,\n });\n }\n\n return { success: true, game } as const;\n}\n","import { addItemToCollection, emitEvent } from \"@hellacardgames/lib\";\nimport type { ChatMessage } from \"../types/ChatMessage.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function sendChat(game: Game, playerId: string, text: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const message: ChatMessage = {\n id: crypto.randomUUID(),\n username: player.username,\n text,\n };\n\n game = {\n ...game,\n chatMessages: addItemToCollection(game.chatMessages, message),\n };\n\n game = emitEvent(game, { type: \"chat\", message });\n\n return { success: true, game } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n CARDS,\n EXPIRY_EXTENSION_MS,\n MIN_PLAYERS,\n} from \"../constants.js\";\nimport type { CreatedGame, StartedGame } from \"../types/Game.js\";\n\nexport function startGame(game: CreatedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (game.players.indexOf(player) !== 0) {\n return { success: false, error: \"playerNotAdmin\" } as const;\n }\n if (game.players.length < MIN_PLAYERS) {\n return { success: false, error: \"minPlayersNotReached\" } as const;\n }\n const otherPlayer = game.players[1]!;\n const cards = [...CARDS];\n shuffleCards(cards);\n\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n\n player.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: player.username,\n numCards: player.drawPile.length,\n });\n\n player.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(player, { type: \"handInitialized\", cards: player.hand });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: player.username,\n numCards: player.hand.length,\n });\n\n otherPlayer.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.drawPile.length,\n });\n\n otherPlayer.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(otherPlayer, {\n type: \"handInitialized\",\n cards: otherPlayer.hand,\n });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.hand.length,\n });\n\n const startedGame: StartedGame = {\n ...game,\n status: \"started\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS,\n };\n // this.games.set(game.id, startedGame);\n emitEvent(startedGame, { type: \"gameStarted\" });\n emitEvent(startedGame, {\n type: \"expirationUpdated\",\n expiresAt: startedGame.expiresAt,\n });\n emitEvent(startedGame, {\n type: \"canPlayAtUpdated\",\n canPlayAt: startedGame.canPlayAt,\n });\n return { success: true, game: startedGame } as const;\n}\n","import { createManagerFactory } from \"@hellacardgames/lib\";\nimport {\n createGame,\n drawCard,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n MAX_PLAYERS,\n playCard,\n reportNoPlayableCards,\n sendChat,\n startGame,\n} from \"../game/index.js\";\n\nexport const createManager = createManagerFactory({\n maxPlayers: MAX_PLAYERS,\n createGame,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n sendChat,\n startGame,\n createCustomActions: (games) => ({\n drawCard: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = drawCard(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n playCard: (\n gameId: string,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n ) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = playCard(game, playerId, cardId, isForOtherPlayerPile);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n reportNoPlayableCards: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = reportNoPlayableCards(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n }),\n});\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manager-C6MB3C6o.cjs","names":["emitEvent","doGetEventsAndClearAcknowledged","addItemToCollection","emitEvent","createManagerFactory"],"sources":["../src/game/constants.ts","../src/game/actions/createGame.ts","../src/game/lib/emitEvent.ts","../src/game/lib/emitEventToPlayer.ts","../src/game/actions/drawCard.ts","../src/game/actions/getClientStateAndClearEvents.ts","../src/game/actions/getEventsAndClearAcknowledged.ts","../src/game/actions/joinGame.ts","../src/game/actions/leaveGame.ts","../src/game/lib/isCardPlayable.ts","../src/game/lib/hasPlayableCard.ts","../src/game/actions/playCard.ts","../src/game/lib/shuffleCards.ts","../src/game/actions/reportNoPlayableCards.ts","../src/game/actions/sendChat.ts","../src/game/actions/startGame.ts","../src/manager/createManager.ts"],"sourcesContent":["import type { Card } from \"./types/Card.js\";\n\nexport const EXPIRY_EXTENSION_MS = 300000; // 5 minutes\nexport const MIN_PLAYERS = 2;\nexport const MAX_PLAYERS = 2;\nexport const MAX_HAND_SIZE = 5;\nexport const CAN_PLAY_AT_DELAY_MS = 3000;\n\nexport const CARDS: readonly Card[] = [\n { id: crypto.randomUUID(), rank: 2, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"clubs\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"diamonds\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"hearts\" },\n { id: crypto.randomUUID(), rank: 2, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 3, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 4, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 5, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 6, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 7, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 8, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 9, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 10, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 11, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 12, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 13, suite: \"spades\" },\n { id: crypto.randomUUID(), rank: 14, suite: \"spades\" },\n];\n","import { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function createGame(userId: string, username: string) {\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n\n const createdAt = Date.now();\n\n const game: CreatedGame = {\n status: \"created\",\n id: crypto.randomUUID(),\n createdAt,\n expiresAt: createdAt + EXPIRY_EXTENSION_MS,\n chatMessages: [],\n players: [player],\n };\n\n return { game, playerId: player.id } as const;\n}\n","type Game = {\n readonly players: {\n readonly events: { readonly id: string }[];\n }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEvent<T extends Game>(\n game: T,\n data: OmitId<T[\"players\"][number][\"events\"][number]>,\n): void {\n const event = { ...data, id: crypto.randomUUID() };\n for (const p of game.players) {\n p.events.push(event);\n }\n}\n","type Player = {\n readonly events: { readonly id: string }[];\n};\n\ntype OmitId<T> = T extends unknown ? Omit<T, \"id\"> : never;\n\nexport function emitEventToPlayer<T extends Player>(\n player: T,\n data: OmitId<T[\"events\"][number]>,\n): void {\n player.events.push({ ...data, id: crypto.randomUUID() });\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { EXPIRY_EXTENSION_MS, MAX_HAND_SIZE } from \"../constants.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function drawCard(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hand.length >= MAX_HAND_SIZE) {\n return { success: false, error: \"handFull\" } as const;\n }\n if (player.drawPile.length === 0) {\n return { success: false, error: \"drawPileEmpty\" } as const;\n }\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n const card = player.drawPile.pop()!;\n player.hand.push(card);\n emitEventToPlayer(player, { type: \"drewCard\", card });\n emitEvent(game, { type: \"playerDrewCard\", username: player.username });\n return { success: true, game } as const;\n}\n","import type { ClientState } from \"../types/ClientState.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getClientStateAndClearEvents(game: Game, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n const state: ClientState = {\n status: game.status,\n gameId: game.id,\n playerId,\n username: player.username,\n players: game.players.map((p) => ({\n username: p.username,\n handSize: p.hand.length,\n drawPileSize: p.drawPile.length,\n sidePileSize: p.sidePile.length,\n centerPileTopCard: p.centerPile.length\n ? p.centerPile[p.centerPile.length - 1]!\n : null,\n })),\n expiresAt: game.expiresAt,\n chatMessages: game.chatMessages,\n hand: player.hand,\n canPlayAt: game.status === \"started\" ? game.canPlayAt : null,\n };\n player.events.length = 0;\n return { success: true, state, game } as const;\n}\n","import { getEventsAndClearAcknowledged as doGetEventsAndClearAcknowledged } from \"@hellacardgames/lib\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function getEventsAndClearAcknowledged(\n game: Game,\n playerId: string,\n lastReadId: string | null,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const result = doGetEventsAndClearAcknowledged(game, player.id, lastReadId);\n\n return {\n success: true,\n events: result.events,\n game: result.game,\n } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { MAX_PLAYERS } from \"../constants.js\";\nimport type { CreatedGame } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function joinGame(game: CreatedGame, userId: string, username: string) {\n if (game.players.length === MAX_PLAYERS) {\n return { success: false, error: \"maxPlayersReached\" } as const;\n }\n if (game.players.find((p) => p.userId === userId)) {\n return { success: false, error: \"alreadyInGame\" } as const;\n }\n const player: Player = {\n id: crypto.randomUUID(),\n userId,\n username,\n events: [],\n hand: [],\n drawPile: [],\n sidePile: [],\n centerPile: [],\n hasNoPlayableCards: false,\n };\n game.players.push(player);\n emitEvent(game, { type: \"playerJoined\", username });\n return { success: true, game, playerId: player.id } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS, MIN_PLAYERS } from \"../constants.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function leaveGame(game: Game, playerId: string) {\n const playerIndex = game.players.findIndex((p) => p.id === playerId);\n if (playerIndex === -1) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const player = game.players[playerIndex]!;\n emitEvent(game, { type: \"playerLeft\", username: player.username });\n\n game.players.splice(playerIndex, 1);\n\n if (game.status === \"started\" && game.players.length < MIN_PLAYERS) {\n const forfeitedGame: Game = {\n ...game,\n status: \"forfeited\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n };\n // this.games.set(game.id, forfeitedGame);\n emitEvent(forfeitedGame, { type: \"gameForfeited\" });\n emitEvent(forfeitedGame, {\n type: \"expirationUpdated\",\n expiresAt: forfeitedGame.expiresAt,\n });\n return { success: true, game: forfeitedGame } as const;\n }\n return { success: true, game } as const;\n}\n","import type { Card } from \"../types/Card.js\";\n\nexport function isCardPlayable(card: Card, targetPile: Card[]) {\n const targetCard = targetPile[targetPile.length - 1]!;\n const diff = Math.abs(card.rank - targetCard.rank) % 11;\n return diff === 1;\n}\n","import { isCardPlayable } from \"./isCardPlayable.js\";\nimport type { Game } from \"../types/Game.js\";\nimport type { Player } from \"../types/Player.js\";\n\nexport function hasPlayableCard(player: Player, game: Game) {\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile1 = player.centerPile;\n const targetPile2 = otherPlayer.centerPile;\n for (const card of player.hand) {\n if (\n isCardPlayable(card, targetPile1) ||\n isCardPlayable(card, targetPile2)\n ) {\n return true;\n }\n }\n return false;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { EXPIRY_EXTENSION_MS } from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport { isCardPlayable } from \"../lib/isCardPlayable.js\";\nimport type { CompletedGame, StartedGame } from \"../types/Game.js\";\n\nexport function playCard(\n game: StartedGame,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n const cardIndex = player.hand.findIndex((c) => c.id === cardId);\n if (cardIndex === -1) {\n return { success: false, error: \"cardNotFound\" } as const;\n }\n const otherPlayer = game.players.find((p) => p !== player)!;\n const targetPile = isForOtherPlayerPile\n ? otherPlayer.centerPile\n : player.centerPile;\n const card = player.hand[cardIndex]!;\n if (!isCardPlayable(card, targetPile)) {\n return { success: false, error: \"cardNotPlayable\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hand.splice(cardIndex, 1);\n targetPile.push(card);\n emitEvent(game, {\n type: \"cardPlayed\",\n username: player.username,\n card,\n isForOtherPlayerPile,\n });\n\n if (otherPlayer.hasNoPlayableCards && hasPlayableCard(otherPlayer, game)) {\n otherPlayer.hasNoPlayableCards = false;\n }\n\n if (player.hand.length === 0 && player.drawPile.length === 0) {\n emitEvent(game, { type: \"gameCompleted\" });\n const completedGame: CompletedGame = {\n ...game,\n status: \"completed\",\n };\n return { success: true, game: completedGame } as const;\n }\n\n return { success: true, game } as const;\n}\n","type Card = { readonly id: string };\n\nexport function shuffleCards<T extends Card>(cards: T[]): void {\n for (let i = cards.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [cards[i], cards[j]] = [cards[j]!, cards[i]!];\n }\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n EXPIRY_EXTENSION_MS,\n MAX_HAND_SIZE,\n} from \"../constants.js\";\nimport { hasPlayableCard } from \"../lib/hasPlayableCard.js\";\nimport type { StartedGame } from \"../types/Game.js\";\n\nexport function reportNoPlayableCards(game: StartedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (Date.now() < game.canPlayAt) {\n return { success: false, error: \"canPlayAtNotReached\" } as const;\n }\n if (player.hasNoPlayableCards) {\n return { success: false, error: \"alreadyReported\" } as const;\n }\n if (hasPlayableCard(player, game)) {\n return { success: false, error: \"hasPlayableCard\" } as const;\n }\n if (player.drawPile.length > 0 && player.hand.length < MAX_HAND_SIZE) {\n return { success: false, error: \"canDraw\" } as const;\n }\n\n game.expiresAt = Date.now() + EXPIRY_EXTENSION_MS;\n emitEvent(game, { type: \"expirationUpdated\", expiresAt: game.expiresAt });\n\n player.hasNoPlayableCards = true;\n\n const otherPlayer = game.players.find((p) => p !== player)!;\n if (otherPlayer.hasNoPlayableCards) {\n if (player.sidePile.length === 0 && otherPlayer.sidePile.length === 0) {\n const cards = [...player.centerPile, ...otherPlayer.centerPile];\n shuffleCards(cards);\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n } else {\n const playerSidePileCard = player.sidePile.pop()!;\n player.centerPile.push(playerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: player.username,\n card: playerSidePileCard,\n });\n const otherPlayerSidePileCard = otherPlayer.sidePile.pop()!;\n otherPlayer.centerPile.push(otherPlayerSidePileCard);\n emitEvent(game, {\n type: \"cardDrawnFromSidePileToCenterPile\",\n username: otherPlayer.username,\n card: otherPlayerSidePileCard,\n });\n }\n player.hasNoPlayableCards = false;\n otherPlayer.hasNoPlayableCards = false;\n game.canPlayAt = Date.now() + CAN_PLAY_AT_DELAY_MS;\n emitEvent(game, {\n type: \"canPlayAtUpdated\",\n canPlayAt: game.canPlayAt,\n });\n }\n\n return { success: true, game } as const;\n}\n","import { addItemToCollection, emitEvent } from \"@hellacardgames/lib\";\nimport type { ChatMessage } from \"../types/ChatMessage.js\";\nimport type { Game } from \"../types/Game.js\";\n\nexport function sendChat(game: Game, playerId: string, text: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n\n const message: ChatMessage = {\n id: crypto.randomUUID(),\n username: player.username,\n text,\n };\n\n game = {\n ...game,\n chatMessages: addItemToCollection(game.chatMessages, message),\n };\n\n game = emitEvent(game, { type: \"chat\", message });\n\n return { success: true, game } as const;\n}\n","import { emitEvent } from \"../lib/emitEvent.js\";\nimport { emitEventToPlayer } from \"../lib/emitEventToPlayer.js\";\nimport { shuffleCards } from \"../lib/shuffleCards.js\";\nimport {\n CAN_PLAY_AT_DELAY_MS,\n CARDS,\n EXPIRY_EXTENSION_MS,\n MIN_PLAYERS,\n} from \"../constants.js\";\nimport type { CreatedGame, StartedGame } from \"../types/Game.js\";\n\nexport function startGame(game: CreatedGame, playerId: string) {\n const player = game.players.find((p) => p.id === playerId);\n if (!player) {\n return { success: false, error: \"playerNotFound\" } as const;\n }\n if (game.players.indexOf(player) !== 0) {\n return { success: false, error: \"playerNotAdmin\" } as const;\n }\n if (game.players.length < MIN_PLAYERS) {\n return { success: false, error: \"minPlayersNotReached\" } as const;\n }\n const otherPlayer = game.players[1]!;\n const cards = [...CARDS];\n shuffleCards(cards);\n\n player.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: player.username,\n numCards: player.sidePile.length,\n });\n\n player.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: player.username,\n card: player.centerPile[player.centerPile.length - 1]!,\n });\n\n otherPlayer.centerPile.push(...cards.splice(0, 1));\n emitEvent(game, {\n type: \"playerCenterPileInitialized\",\n username: otherPlayer.username,\n card: otherPlayer.centerPile[otherPlayer.centerPile.length - 1]!,\n });\n\n otherPlayer.sidePile.push(...cards.splice(0, 5));\n emitEvent(game, {\n type: \"playerSidePileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.sidePile.length,\n });\n\n player.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: player.username,\n numCards: player.drawPile.length,\n });\n\n player.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(player, { type: \"handInitialized\", cards: player.hand });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: player.username,\n numCards: player.hand.length,\n });\n\n otherPlayer.drawPile.push(...cards.splice(0, 15));\n emitEvent(game, {\n type: \"playerDrawPileInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.drawPile.length,\n });\n\n otherPlayer.hand.push(...cards.splice(0, 5));\n emitEventToPlayer(otherPlayer, {\n type: \"handInitialized\",\n cards: otherPlayer.hand,\n });\n emitEvent(game, {\n type: \"playerHandInitialized\",\n username: otherPlayer.username,\n numCards: otherPlayer.hand.length,\n });\n\n const startedGame: StartedGame = {\n ...game,\n status: \"started\",\n expiresAt: Date.now() + EXPIRY_EXTENSION_MS,\n canPlayAt: Date.now() + CAN_PLAY_AT_DELAY_MS,\n };\n // this.games.set(game.id, startedGame);\n emitEvent(startedGame, { type: \"gameStarted\" });\n emitEvent(startedGame, {\n type: \"expirationUpdated\",\n expiresAt: startedGame.expiresAt,\n });\n emitEvent(startedGame, {\n type: \"canPlayAtUpdated\",\n canPlayAt: startedGame.canPlayAt,\n });\n return { success: true, game: startedGame } as const;\n}\n","import { createManagerFactory } from \"@hellacardgames/lib\";\nimport {\n createGame,\n drawCard,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n MAX_PLAYERS,\n playCard,\n reportNoPlayableCards,\n sendChat,\n startGame,\n} from \"../game/index.js\";\n\nexport const createManager = createManagerFactory({\n maxPlayers: MAX_PLAYERS,\n createGame,\n getClientStateAndClearEvents,\n getEventsAndClearAcknowledged,\n joinGame,\n leaveGame,\n sendChat,\n startGame,\n createCustomActions: (games) => ({\n drawCard: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = drawCard(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n playCard: (\n gameId: string,\n playerId: string,\n cardId: string,\n isForOtherPlayerPile: boolean,\n ) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = playCard(game, playerId, cardId, isForOtherPlayerPile);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n reportNoPlayableCards: (gameId: string, playerId: string) => {\n const game = games.get(gameId);\n if (!game) {\n return { success: false, error: \"gameNotFound\" } as const;\n }\n if (game.status !== \"started\") {\n return { success: false, error: \"invalidStatus\" } as const;\n }\n const result = reportNoPlayableCards(game, playerId);\n if (!result.success) {\n return { success: false, error: result.error } as const;\n }\n games.set(gameId, result.game);\n return { success: true } as const;\n },\n }),\n});\n"],"mappings":";;AAEA,MAAa,sBAAsB;AAInC,MAAa,uBAAuB;AAEpC,MAAa,QAAyB;CACpC;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAQ;CACnD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAQ;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAQ;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAQ;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAQ;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAQ;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAW;CACtD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAW;CACvD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAW;CACvD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAW;CACvD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAW;CACvD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAW;CACvD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAG,OAAO;CAAS;CACpD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;CACrD;EAAE,IAAI,OAAO,WAAW;EAAG,MAAM;EAAI,OAAO;CAAS;AACvD;;;ACzDA,SAAgB,WAAW,QAAgB,UAAkB;CAC3D,MAAM,SAAiB;EACrB,IAAI,OAAO,WAAW;EACtB;EACA;EACA,QAAQ,CAAC;EACT,MAAM,CAAC;EACP,UAAU,CAAC;EACX,UAAU,CAAC;EACX,YAAY,CAAC;EACb,oBAAoB;CACtB;CAEA,MAAM,YAAY,KAAK,IAAI;CAW3B,OAAO;EAAE,MAAA;GARP,QAAQ;GACR,IAAI,OAAO,WAAW;GACtB;GACA,WAAW,YAAY;GACvB,cAAc,CAAC;GACf,SAAS,CAAC,MAAM;EAGN;EAAG,UAAU,OAAO;CAAG;AACrC;;;ACrBA,SAAgBA,YACd,MACA,MACM;CACN,MAAM,QAAQ;EAAE,GAAG;EAAM,IAAI,OAAO,WAAW;CAAE;CACjD,KAAK,MAAM,KAAK,KAAK,SACnB,EAAE,OAAO,KAAK,KAAK;AAEvB;;;ACVA,SAAgB,kBACd,QACA,MACM;CACN,OAAO,OAAO,KAAK;EAAE,GAAG;EAAM,IAAI,OAAO,WAAW;CAAE,CAAC;AACzD;;;ACNA,SAAgB,SAAS,MAAmB,UAAkB;CAC5D,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,IAAI,KAAK,IAAI,IAAI,KAAK,WACpB,OAAO;EAAE,SAAS;EAAO,OAAO;CAAsB;CAExD,IAAI,OAAO,KAAK,UAAA,GACd,OAAO;EAAE,SAAS;EAAO,OAAO;CAAW;CAE7C,IAAI,OAAO,SAAS,WAAW,GAC7B,OAAO;EAAE,SAAS;EAAO,OAAO;CAAgB;CAElD,KAAK,YAAY,KAAK,IAAI,IAAI;CAC9B,YAAU,MAAM;EAAE,MAAM;EAAqB,WAAW,KAAK;CAAU,CAAC;CACxE,MAAM,OAAO,OAAO,SAAS,IAAI;CACjC,OAAO,KAAK,KAAK,IAAI;CACrB,kBAAkB,QAAQ;EAAE,MAAM;EAAY;CAAK,CAAC;CACpD,YAAU,MAAM;EAAE,MAAM;EAAkB,UAAU,OAAO;CAAS,CAAC;CACrE,OAAO;EAAE,SAAS;EAAM;CAAK;AAC/B;;;ACvBA,SAAgB,6BAA6B,MAAY,UAAkB;CACzE,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,MAAM,QAAqB;EACzB,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb;EACA,UAAU,OAAO;EACjB,SAAS,KAAK,QAAQ,KAAK,OAAO;GAChC,UAAU,EAAE;GACZ,UAAU,EAAE,KAAK;GACjB,cAAc,EAAE,SAAS;GACzB,cAAc,EAAE,SAAS;GACzB,mBAAmB,EAAE,WAAW,SAC5B,EAAE,WAAW,EAAE,WAAW,SAAS,KACnC;EACN,EAAE;EACF,WAAW,KAAK;EAChB,cAAc,KAAK;EACnB,MAAM,OAAO;EACb,WAAW,KAAK,WAAW,YAAY,KAAK,YAAY;CAC1D;CACA,OAAO,OAAO,SAAS;CACvB,OAAO;EAAE,SAAS;EAAM;EAAO;CAAK;AACtC;;;AC1BA,SAAgB,8BACd,MACA,UACA,YACA;CACA,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAGnD,MAAM,UAAA,GAASC,oBAAAA,8BAAAA,CAAgC,MAAM,OAAO,IAAI,UAAU;CAE1E,OAAO;EACL,SAAS;EACT,QAAQ,OAAO;EACf,MAAM,OAAO;CACf;AACF;;;ACfA,SAAgB,SAAS,MAAmB,QAAgB,UAAkB;CAC5E,IAAI,KAAK,QAAQ,WAAA,GACf,OAAO;EAAE,SAAS;EAAO,OAAO;CAAoB;CAEtD,IAAI,KAAK,QAAQ,MAAM,MAAM,EAAE,WAAW,MAAM,GAC9C,OAAO;EAAE,SAAS;EAAO,OAAO;CAAgB;CAElD,MAAM,SAAiB;EACrB,IAAI,OAAO,WAAW;EACtB;EACA;EACA,QAAQ,CAAC;EACT,MAAM,CAAC;EACP,UAAU,CAAC;EACX,UAAU,CAAC;EACX,YAAY,CAAC;EACb,oBAAoB;CACtB;CACA,KAAK,QAAQ,KAAK,MAAM;CACxB,YAAU,MAAM;EAAE,MAAM;EAAgB;CAAS,CAAC;CAClD,OAAO;EAAE,SAAS;EAAM;EAAM,UAAU,OAAO;CAAG;AACpD;;;ACtBA,SAAgB,UAAU,MAAY,UAAkB;CACtD,MAAM,cAAc,KAAK,QAAQ,WAAW,MAAM,EAAE,OAAO,QAAQ;CACnE,IAAI,gBAAgB,IAClB,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAGnD,MAAM,SAAS,KAAK,QAAQ;CAC5B,YAAU,MAAM;EAAE,MAAM;EAAc,UAAU,OAAO;CAAS,CAAC;CAEjE,KAAK,QAAQ,OAAO,aAAa,CAAC;CAElC,IAAI,KAAK,WAAW,aAAa,KAAK,QAAQ,SAAA,GAAsB;EAClE,MAAM,gBAAsB;GAC1B,GAAG;GACH,QAAQ;GACR,WAAW,KAAK,IAAI,IAAI;EAC1B;EAEA,YAAU,eAAe,EAAE,MAAM,gBAAgB,CAAC;EAClD,YAAU,eAAe;GACvB,MAAM;GACN,WAAW,cAAc;EAC3B,CAAC;EACD,OAAO;GAAE,SAAS;GAAM,MAAM;EAAc;CAC9C;CACA,OAAO;EAAE,SAAS;EAAM;CAAK;AAC/B;;;AC5BA,SAAgB,eAAe,MAAY,YAAoB;CAC7D,MAAM,aAAa,WAAW,WAAW,SAAS;CAElD,OADa,KAAK,IAAI,KAAK,OAAO,WAAW,IAAI,IAAI,OACrC;AAClB;;;ACFA,SAAgB,gBAAgB,QAAgB,MAAY;CAC1D,MAAM,cAAc,KAAK,QAAQ,MAAM,MAAM,MAAM,MAAM;CACzD,MAAM,cAAc,OAAO;CAC3B,MAAM,cAAc,YAAY;CAChC,KAAK,MAAM,QAAQ,OAAO,MACxB,IACE,eAAe,MAAM,WAAW,KAChC,eAAe,MAAM,WAAW,GAEhC,OAAO;CAGX,OAAO;AACT;;;ACXA,SAAgB,SACd,MACA,UACA,QACA,sBACA;CACA,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,IAAI,KAAK,IAAI,IAAI,KAAK,WACpB,OAAO;EAAE,SAAS;EAAO,OAAO;CAAsB;CAExD,MAAM,YAAY,OAAO,KAAK,WAAW,MAAM,EAAE,OAAO,MAAM;CAC9D,IAAI,cAAc,IAChB,OAAO;EAAE,SAAS;EAAO,OAAO;CAAe;CAEjD,MAAM,cAAc,KAAK,QAAQ,MAAM,MAAM,MAAM,MAAM;CACzD,MAAM,aAAa,uBACf,YAAY,aACZ,OAAO;CACX,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,eAAe,MAAM,UAAU,GAClC,OAAO;EAAE,SAAS;EAAO,OAAO;CAAkB;CAGpD,KAAK,YAAY,KAAK,IAAI,IAAI;CAC9B,YAAU,MAAM;EAAE,MAAM;EAAqB,WAAW,KAAK;CAAU,CAAC;CAExE,OAAO,KAAK,OAAO,WAAW,CAAC;CAC/B,WAAW,KAAK,IAAI;CACpB,YAAU,MAAM;EACd,MAAM;EACN,UAAU,OAAO;EACjB;EACA;CACF,CAAC;CAED,IAAI,YAAY,sBAAsB,gBAAgB,aAAa,IAAI,GACrE,YAAY,qBAAqB;CAGnC,IAAI,OAAO,KAAK,WAAW,KAAK,OAAO,SAAS,WAAW,GAAG;EAC5D,YAAU,MAAM,EAAE,MAAM,gBAAgB,CAAC;EAKzC,OAAO;GAAE,SAAS;GAAM,MAAM;IAH5B,GAAG;IACH,QAAQ;GAEgC;EAAE;CAC9C;CAEA,OAAO;EAAE,SAAS;EAAM;CAAK;AAC/B;;;ACxDA,SAAgB,aAA6B,OAAkB;CAC7D,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;EACzC,MAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE;EAC5C,CAAC,MAAM,IAAI,MAAM,MAAM,CAAC,MAAM,IAAK,MAAM,EAAG;CAC9C;AACF;;;ACGA,SAAgB,sBAAsB,MAAmB,UAAkB;CACzE,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,IAAI,KAAK,IAAI,IAAI,KAAK,WACpB,OAAO;EAAE,SAAS;EAAO,OAAO;CAAsB;CAExD,IAAI,OAAO,oBACT,OAAO;EAAE,SAAS;EAAO,OAAO;CAAkB;CAEpD,IAAI,gBAAgB,QAAQ,IAAI,GAC9B,OAAO;EAAE,SAAS;EAAO,OAAO;CAAkB;CAEpD,IAAI,OAAO,SAAS,SAAS,KAAK,OAAO,KAAK,SAAA,GAC5C,OAAO;EAAE,SAAS;EAAO,OAAO;CAAU;CAG5C,KAAK,YAAY,KAAK,IAAI,IAAI;CAC9B,YAAU,MAAM;EAAE,MAAM;EAAqB,WAAW,KAAK;CAAU,CAAC;CAExE,OAAO,qBAAqB;CAE5B,MAAM,cAAc,KAAK,QAAQ,MAAM,MAAM,MAAM,MAAM;CACzD,IAAI,YAAY,oBAAoB;EAClC,IAAI,OAAO,SAAS,WAAW,KAAK,YAAY,SAAS,WAAW,GAAG;GACrE,MAAM,QAAQ,CAAC,GAAG,OAAO,YAAY,GAAG,YAAY,UAAU;GAC9D,aAAa,KAAK;GAClB,OAAO,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;GAC1C,YAAU,MAAM;IACd,MAAM;IACN,UAAU,OAAO;IACjB,UAAU,OAAO,SAAS;GAC5B,CAAC;GACD,OAAO,WAAW,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;GAC5C,YAAU,MAAM;IACd,MAAM;IACN,UAAU,OAAO;IACjB,MAAM,OAAO,WAAW,OAAO,WAAW,SAAS;GACrD,CAAC;GACD,YAAY,WAAW,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;GACjD,YAAU,MAAM;IACd,MAAM;IACN,UAAU,YAAY;IACtB,MAAM,YAAY,WAAW,YAAY,WAAW,SAAS;GAC/D,CAAC;GACD,YAAY,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;GAC/C,YAAU,MAAM;IACd,MAAM;IACN,UAAU,YAAY;IACtB,UAAU,YAAY,SAAS;GACjC,CAAC;EACH,OAAO;GACL,MAAM,qBAAqB,OAAO,SAAS,IAAI;GAC/C,OAAO,WAAW,KAAK,kBAAkB;GACzC,YAAU,MAAM;IACd,MAAM;IACN,UAAU,OAAO;IACjB,MAAM;GACR,CAAC;GACD,MAAM,0BAA0B,YAAY,SAAS,IAAI;GACzD,YAAY,WAAW,KAAK,uBAAuB;GACnD,YAAU,MAAM;IACd,MAAM;IACN,UAAU,YAAY;IACtB,MAAM;GACR,CAAC;EACH;EACA,OAAO,qBAAqB;EAC5B,YAAY,qBAAqB;EACjC,KAAK,YAAY,KAAK,IAAI,IAAI;EAC9B,YAAU,MAAM;GACd,MAAM;GACN,WAAW,KAAK;EAClB,CAAC;CACH;CAEA,OAAO;EAAE,SAAS;EAAM;CAAK;AAC/B;;;ACpFA,SAAgB,SAAS,MAAY,UAAkB,MAAc;CACnE,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAGnD,MAAM,UAAuB;EAC3B,IAAI,OAAO,WAAW;EACtB,UAAU,OAAO;EACjB;CACF;CAEA,OAAO;EACL,GAAG;EACH,eAAA,GAAcC,oBAAAA,oBAAAA,CAAoB,KAAK,cAAc,OAAO;CAC9D;CAEA,QAAA,GAAOC,oBAAAA,UAAAA,CAAU,MAAM;EAAE,MAAM;EAAQ;CAAQ,CAAC;CAEhD,OAAO;EAAE,SAAS;EAAM;CAAK;AAC/B;;;ACbA,SAAgB,UAAU,MAAmB,UAAkB;CAC7D,MAAM,SAAS,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,QAAQ;CACzD,IAAI,CAAC,QACH,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,IAAI,KAAK,QAAQ,QAAQ,MAAM,MAAM,GACnC,OAAO;EAAE,SAAS;EAAO,OAAO;CAAiB;CAEnD,IAAI,KAAK,QAAQ,SAAA,GACf,OAAO;EAAE,SAAS;EAAO,OAAO;CAAuB;CAEzD,MAAM,cAAc,KAAK,QAAQ;CACjC,MAAM,QAAQ,CAAC,GAAG,KAAK;CACvB,aAAa,KAAK;CAElB,OAAO,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CAC1C,YAAU,MAAM;EACd,MAAM;EACN,UAAU,OAAO;EACjB,UAAU,OAAO,SAAS;CAC5B,CAAC;CAED,OAAO,WAAW,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CAC5C,YAAU,MAAM;EACd,MAAM;EACN,UAAU,OAAO;EACjB,MAAM,OAAO,WAAW,OAAO,WAAW,SAAS;CACrD,CAAC;CAED,YAAY,WAAW,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CACjD,YAAU,MAAM;EACd,MAAM;EACN,UAAU,YAAY;EACtB,MAAM,YAAY,WAAW,YAAY,WAAW,SAAS;CAC/D,CAAC;CAED,YAAY,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CAC/C,YAAU,MAAM;EACd,MAAM;EACN,UAAU,YAAY;EACtB,UAAU,YAAY,SAAS;CACjC,CAAC;CAED,OAAO,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,EAAE,CAAC;CAC3C,YAAU,MAAM;EACd,MAAM;EACN,UAAU,OAAO;EACjB,UAAU,OAAO,SAAS;CAC5B,CAAC;CAED,OAAO,KAAK,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CACtC,kBAAkB,QAAQ;EAAE,MAAM;EAAmB,OAAO,OAAO;CAAK,CAAC;CACzE,YAAU,MAAM;EACd,MAAM;EACN,UAAU,OAAO;EACjB,UAAU,OAAO,KAAK;CACxB,CAAC;CAED,YAAY,SAAS,KAAK,GAAG,MAAM,OAAO,GAAG,EAAE,CAAC;CAChD,YAAU,MAAM;EACd,MAAM;EACN,UAAU,YAAY;EACtB,UAAU,YAAY,SAAS;CACjC,CAAC;CAED,YAAY,KAAK,KAAK,GAAG,MAAM,OAAO,GAAG,CAAC,CAAC;CAC3C,kBAAkB,aAAa;EAC7B,MAAM;EACN,OAAO,YAAY;CACrB,CAAC;CACD,YAAU,MAAM;EACd,MAAM;EACN,UAAU,YAAY;EACtB,UAAU,YAAY,KAAK;CAC7B,CAAC;CAED,MAAM,cAA2B;EAC/B,GAAG;EACH,QAAQ;EACR,WAAW,KAAK,IAAI,IAAI;EACxB,WAAW,KAAK,IAAI,IAAI;CAC1B;CAEA,YAAU,aAAa,EAAE,MAAM,cAAc,CAAC;CAC9C,YAAU,aAAa;EACrB,MAAM;EACN,WAAW,YAAY;CACzB,CAAC;CACD,YAAU,aAAa;EACrB,MAAM;EACN,WAAW,YAAY;CACzB,CAAC;CACD,OAAO;EAAE,SAAS;EAAM,MAAM;CAAY;AAC5C;;;ACzFA,MAAa,iBAAA,GAAgBC,oBAAAA,qBAAAA,CAAqB;CAChD,YAAA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,sBAAsB,WAAW;EAC/B,WAAW,QAAgB,aAAqB;GAC9C,MAAM,OAAO,MAAM,IAAI,MAAM;GAC7B,IAAI,CAAC,MACH,OAAO;IAAE,SAAS;IAAO,OAAO;GAAe;GAEjD,IAAI,KAAK,WAAW,WAClB,OAAO;IAAE,SAAS;IAAO,OAAO;GAAgB;GAElD,MAAM,SAAS,SAAS,MAAM,QAAQ;GACtC,IAAI,CAAC,OAAO,SACV,OAAO;IAAE,SAAS;IAAO,OAAO,OAAO;GAAM;GAE/C,MAAM,IAAI,QAAQ,OAAO,IAAI;GAC7B,OAAO,EAAE,SAAS,KAAK;EACzB;EACA,WACE,QACA,UACA,QACA,yBACG;GACH,MAAM,OAAO,MAAM,IAAI,MAAM;GAC7B,IAAI,CAAC,MACH,OAAO;IAAE,SAAS;IAAO,OAAO;GAAe;GAEjD,IAAI,KAAK,WAAW,WAClB,OAAO;IAAE,SAAS;IAAO,OAAO;GAAgB;GAElD,MAAM,SAAS,SAAS,MAAM,UAAU,QAAQ,oBAAoB;GACpE,IAAI,CAAC,OAAO,SACV,OAAO;IAAE,SAAS;IAAO,OAAO,OAAO;GAAM;GAE/C,MAAM,IAAI,QAAQ,OAAO,IAAI;GAC7B,OAAO,EAAE,SAAS,KAAK;EACzB;EACA,wBAAwB,QAAgB,aAAqB;GAC3D,MAAM,OAAO,MAAM,IAAI,MAAM;GAC7B,IAAI,CAAC,MACH,OAAO;IAAE,SAAS;IAAO,OAAO;GAAe;GAEjD,IAAI,KAAK,WAAW,WAClB,OAAO;IAAE,SAAS;IAAO,OAAO;GAAgB;GAElD,MAAM,SAAS,sBAAsB,MAAM,QAAQ;GACnD,IAAI,CAAC,OAAO,SACV,OAAO;IAAE,SAAS;IAAO,OAAO,OAAO;GAAM;GAE/C,MAAM,IAAI,QAAQ,OAAO,IAAI;GAC7B,OAAO,EAAE,SAAS,KAAK;EACzB;CACF;AACF,CAAC"}
|