trucoshi 7.0.0-alpha.2 → 7.0.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/lib/classes/Deck.js +20 -6
- package/dist/lib/classes/Queue.d.ts +1 -1
- package/dist/lib/classes/Queue.js +4 -3
- package/dist/lib/classes/Table.js +21 -7
- package/dist/lib/utils.d.ts +1 -2
- package/dist/lib/utils.js +0 -17
- package/dist/types.d.ts +34 -11
- package/dist/types.js +3 -2
- package/package.json +3 -3
- package/dist/server/constants.d.ts +0 -3
- package/dist/server/constants.js +0 -3
package/README.md
CHANGED
package/dist/lib/classes/Deck.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BURNT_CARD, CARDS } from "
|
|
1
|
+
import { BURNT_CARD, CARDS } from "../constants";
|
|
2
2
|
import { Random } from "./Random";
|
|
3
3
|
export function Deck() {
|
|
4
4
|
const deck = {
|
|
@@ -37,6 +37,8 @@ export function Deck() {
|
|
|
37
37
|
export const getAllCards = () => Object.keys(CARDS);
|
|
38
38
|
export function dealCards(table, deck) {
|
|
39
39
|
const cheat_lots_of_flowers = process.env.APP_CHEAT_LOTS_OF_FLOWERS_FOR_TESTING === "1";
|
|
40
|
+
const cheat_cards = process.env.APP_CHEAT_CARDS &&
|
|
41
|
+
JSON.parse(process.env.APP_CHEAT_CARDS);
|
|
40
42
|
const playerHands = [];
|
|
41
43
|
const players = table.getPlayersForehandFirst();
|
|
42
44
|
for (let i = 0; i < 3; i++) {
|
|
@@ -44,13 +46,25 @@ export function dealCards(table, deck) {
|
|
|
44
46
|
playerHands[player.idx] = [...(playerHands[player.idx] || []), deck.takeCard()];
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
|
-
if (
|
|
49
|
+
if (cheat_cards) {
|
|
50
|
+
deck.shuffle(players[0].idx);
|
|
51
|
+
for (const [key, player] of players.entries()) {
|
|
52
|
+
playerHands[player.idx] = cheat_cards[key]
|
|
53
|
+
? cheat_cards[key].map((c) => deck.pick(c) || deck.takeCard())
|
|
54
|
+
: deck.takeThree();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (cheat_lots_of_flowers) {
|
|
48
58
|
deck.shuffle(players[0].idx);
|
|
49
59
|
for (const player of players) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
if (Math.random() > 0.5) {
|
|
61
|
+
const first = deck.takeCard();
|
|
62
|
+
const second = deck.pick(deck.cards.find((c) => c.charAt(1) === first.charAt(1)));
|
|
63
|
+
const third = deck.pick(deck.cards.find((c) => c.charAt(1) === first.charAt(1)));
|
|
64
|
+
playerHands[player.idx] = [first, second, third];
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
playerHands[player.idx] = deck.takeThree();
|
|
54
68
|
}
|
|
55
69
|
}
|
|
56
70
|
for (const [key, player] of table.players.entries()) {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import logger from "../../utils/logger";
|
|
2
|
+
const log = logger.child({ class: "Queue" });
|
|
2
3
|
export const Queue = () => {
|
|
3
4
|
const queue = {
|
|
4
5
|
promise: Promise.resolve(),
|
|
5
6
|
queue(operation) {
|
|
6
|
-
return new Promise((resolve) => {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
7
8
|
queue.promise = queue.promise
|
|
8
9
|
.then(operation)
|
|
9
10
|
.then(resolve)
|
|
10
11
|
.catch((e) => {
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
log.error(e, "Error in queue operation %o", operation);
|
|
13
|
+
reject(e);
|
|
13
14
|
});
|
|
14
15
|
});
|
|
15
16
|
},
|
|
@@ -1,34 +1,48 @@
|
|
|
1
|
+
import logger from "../../utils/logger";
|
|
2
|
+
const log = logger.child({ class: "Table" });
|
|
1
3
|
export function Table(players) {
|
|
4
|
+
log.trace({ playerKeys: players.map((p) => p.key) }, "Creating new table");
|
|
2
5
|
const table = {
|
|
3
6
|
players,
|
|
4
7
|
cards: [],
|
|
5
8
|
forehandIdx: 0,
|
|
6
9
|
nextHand() {
|
|
10
|
+
log.trace({ currentForehandIdx: table.forehandIdx }, "nextHand called");
|
|
7
11
|
if (table.forehandIdx < table.players.length - 1) {
|
|
8
12
|
table.forehandIdx++;
|
|
9
13
|
}
|
|
10
14
|
else {
|
|
11
15
|
table.forehandIdx = 0;
|
|
12
16
|
}
|
|
13
|
-
|
|
17
|
+
log.trace({ newForehandIdx: table.forehandIdx }, "nextHand updated");
|
|
18
|
+
const nextPlayer = table.getPlayerByPosition();
|
|
19
|
+
log.trace({ playerKey: nextPlayer.key }, "nextHand returning player");
|
|
20
|
+
return nextPlayer;
|
|
14
21
|
},
|
|
15
22
|
getPlayerPosition(key, forehandFirst = false) {
|
|
23
|
+
log.trace({ key, forehandFirst }, "getPlayerPosition called");
|
|
16
24
|
const array = forehandFirst ? table.getPlayersForehandFirst() : table.players;
|
|
17
|
-
|
|
25
|
+
const position = array.findIndex((p) => p.key === key);
|
|
26
|
+
log.trace({ key, position }, "getPlayerPosition result");
|
|
27
|
+
return position;
|
|
18
28
|
},
|
|
19
29
|
getPlayersForehandFirst(forehand) {
|
|
20
30
|
const idx = forehand !== undefined ? forehand : table.forehandIdx;
|
|
31
|
+
log.trace({ forehandIdx: idx }, "getPlayersForehandFirst called");
|
|
21
32
|
const cut = players.slice(idx, table.players.length);
|
|
22
33
|
const end = players.slice(0, idx);
|
|
23
|
-
|
|
34
|
+
const result = cut.concat(end);
|
|
35
|
+
log.trace({ playerKeys: result.map((p) => p.key) }, "getPlayersForehandFirst result");
|
|
36
|
+
return result;
|
|
24
37
|
},
|
|
25
38
|
getPlayerByPosition(idx, forehandFirst = false) {
|
|
39
|
+
log.trace({ idx, forehandFirst }, "getPlayerByPosition called");
|
|
26
40
|
const array = forehandFirst ? table.getPlayersForehandFirst() : table.players;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return array[0];
|
|
41
|
+
const player = idx !== undefined ? array[idx] : array[0];
|
|
42
|
+
log.trace({ playerKey: player.key }, "getPlayerByPosition result");
|
|
43
|
+
return player;
|
|
31
44
|
},
|
|
32
45
|
};
|
|
46
|
+
log.trace({ forehandIdx: table.forehandIdx }, "Table initialization complete");
|
|
33
47
|
return table;
|
|
34
48
|
}
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IRound } from "../truco";
|
|
2
|
-
import { ICard
|
|
3
|
-
export declare function calculateFlorPoints(player: IPlayer): number;
|
|
2
|
+
import { ICard } from "../types";
|
|
4
3
|
export declare function getMaxNumberIndex<T = number>(array: Array<T>): number;
|
|
5
4
|
export declare function getMinNumberIndex<T = number>(array: Array<T>): number;
|
|
6
5
|
export declare function getCardValue(card: ICard): number;
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import { splitCardvalues } from "../truco";
|
|
2
1
|
import { CARDS } from "./constants";
|
|
3
|
-
// Calculates the Flor points for a player's hand.
|
|
4
|
-
// Returns the sum of the envidoValue of three cards of the same suit plus 20, or 0 if no Flor exists.
|
|
5
|
-
export function calculateFlorPoints(player) {
|
|
6
|
-
if (!player.hasFlor) {
|
|
7
|
-
return 0;
|
|
8
|
-
}
|
|
9
|
-
const hand = [...player.hand, ...player.usedHand].map(splitCardvalues);
|
|
10
|
-
// Verify that all cards share the same suit (should be true if player.hasFlor is set)
|
|
11
|
-
const sameSuit = hand.every((card) => card.palo === hand[0].palo);
|
|
12
|
-
if (!sameSuit) {
|
|
13
|
-
return 0;
|
|
14
|
-
}
|
|
15
|
-
// Sum the envidoValue of all cards (figures are 0)
|
|
16
|
-
const points = hand.reduce((sum, card) => sum + card.value, 20);
|
|
17
|
-
return points;
|
|
18
|
-
}
|
|
19
2
|
export function getMaxNumberIndex(array) {
|
|
20
3
|
return array.reduce((accumulator, current, index) => {
|
|
21
4
|
return current > array[accumulator] ? index : accumulator;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export * from "./events";
|
|
2
2
|
export { CARDS, CARDS_HUMAN_READABLE, BURNT_CARD } from "./lib/constants";
|
|
3
3
|
import { User } from "lightning-accounts";
|
|
4
|
-
import { CARDS } from "./lib";
|
|
5
4
|
import { Match, MatchPlayer, MatchHand, UserStats } from "@trucoshi/prisma";
|
|
6
5
|
import { IHand } from "./truco";
|
|
6
|
+
import { CARDS } from "./lib";
|
|
7
7
|
export declare enum EMatchState {
|
|
8
8
|
UNREADY = "UNREADY",
|
|
9
9
|
READY = "READY",
|
|
@@ -39,6 +39,16 @@ export interface ISaidCommand {
|
|
|
39
39
|
player: IPlayer | IPublicPlayer;
|
|
40
40
|
command: ECommand | number;
|
|
41
41
|
}
|
|
42
|
+
export interface IMatchFlorBattle {
|
|
43
|
+
matchSessionId: string;
|
|
44
|
+
playersWithFlor: {
|
|
45
|
+
idx: number;
|
|
46
|
+
cards?: ICard[];
|
|
47
|
+
points: number;
|
|
48
|
+
}[];
|
|
49
|
+
winnerTeamIdx: 0 | 1 | null;
|
|
50
|
+
winner: IPublicPlayer | null;
|
|
51
|
+
}
|
|
42
52
|
export interface IMatchPreviousHand {
|
|
43
53
|
envido: {
|
|
44
54
|
winner: IPublicPlayer;
|
|
@@ -48,6 +58,7 @@ export interface IMatchPreviousHand {
|
|
|
48
58
|
};
|
|
49
59
|
} | null;
|
|
50
60
|
flor: {
|
|
61
|
+
winner: IPublicPlayer | null;
|
|
51
62
|
data: Array<{
|
|
52
63
|
idx: number;
|
|
53
64
|
value: number;
|
|
@@ -64,8 +75,10 @@ export interface IPublicMatch {
|
|
|
64
75
|
busy: boolean;
|
|
65
76
|
state: EMatchState;
|
|
66
77
|
handState: EHandState | null;
|
|
78
|
+
florBattle: IMatchFlorBattle | null;
|
|
67
79
|
winner: ITeam | null;
|
|
68
80
|
matchSessionId: string;
|
|
81
|
+
forehandIdx: number;
|
|
69
82
|
ownerKey: string;
|
|
70
83
|
teams: Array<IPublicTeam>;
|
|
71
84
|
players: Array<IPublicPlayer>;
|
|
@@ -89,11 +102,13 @@ export interface IChatMessage {
|
|
|
89
102
|
user: {
|
|
90
103
|
name: string;
|
|
91
104
|
key: string;
|
|
105
|
+
teamIdx?: 0 | 1;
|
|
92
106
|
};
|
|
93
107
|
system?: boolean;
|
|
94
108
|
command?: boolean;
|
|
95
109
|
card?: boolean;
|
|
96
110
|
content: string;
|
|
111
|
+
sound: string | boolean;
|
|
97
112
|
}
|
|
98
113
|
export interface IChatRoom {
|
|
99
114
|
id: string;
|
|
@@ -101,10 +116,10 @@ export interface IChatRoom {
|
|
|
101
116
|
socket: {
|
|
102
117
|
emit(socket: string): void;
|
|
103
118
|
};
|
|
104
|
-
send(user: IChatMessage["user"], message: string): void;
|
|
105
|
-
card(user: IChatMessage["user"], card: ICard): void;
|
|
106
|
-
command(team: 0 | 1, command: ECommand | number): void;
|
|
107
|
-
system(message: string): void;
|
|
119
|
+
send(user: IChatMessage["user"], message: string, sound?: string | boolean): void;
|
|
120
|
+
card(user: IChatMessage["user"], card: ICard, sound?: string | boolean): void;
|
|
121
|
+
command(team: 0 | 1, command: ECommand | number, sound?: string | boolean): void;
|
|
122
|
+
system(message: string, sound?: string | boolean): void;
|
|
108
123
|
emit(message?: IChatMessage): void;
|
|
109
124
|
}
|
|
110
125
|
export declare enum EChatSystem {
|
|
@@ -134,9 +149,9 @@ export declare enum EEnvidoAnswerCommand {
|
|
|
134
149
|
SON_BUENAS = "SON_BUENAS"
|
|
135
150
|
}
|
|
136
151
|
export declare enum EEnvidoCommand {
|
|
137
|
-
|
|
152
|
+
FALTA_ENVIDO = "FALTA_ENVIDO",
|
|
138
153
|
REAL_ENVIDO = "REAL_ENVIDO",
|
|
139
|
-
|
|
154
|
+
ENVIDO = "ENVIDO"
|
|
140
155
|
}
|
|
141
156
|
export declare enum EHandState {
|
|
142
157
|
WAITING_PLAY = "WAITING_PLAY",
|
|
@@ -144,6 +159,7 @@ export declare enum EHandState {
|
|
|
144
159
|
WAITING_ENVIDO_ANSWER = "WAITING_ENVIDO_ANSWER",
|
|
145
160
|
WAITING_ENVIDO_POINTS_ANSWER = "WAITING_ENVIDO_POINTS_ANSWER",
|
|
146
161
|
WAITING_FLOR_ANSWER = "WAITING_FLOR_ANSWER",
|
|
162
|
+
DISPLAY_FLOR_BATTLE = "DISPLAY_FLOR_BATTLE",
|
|
147
163
|
BEFORE_FINISHED = "BEFORE_FINISHED",
|
|
148
164
|
FINISHED = "FINISHED"
|
|
149
165
|
}
|
|
@@ -248,10 +264,10 @@ export type IPublicTeam = Pick<ITeam, "points" | "id" | "name"> & {
|
|
|
248
264
|
export interface IPlayer {
|
|
249
265
|
idx: number;
|
|
250
266
|
secret: string;
|
|
251
|
-
teamIdx:
|
|
267
|
+
teamIdx: 0 | 1;
|
|
252
268
|
accountId: number | undefined;
|
|
253
269
|
matchPlayerId: number | undefined;
|
|
254
|
-
avatarUrl: string | undefined;
|
|
270
|
+
avatarUrl: string | undefined | null;
|
|
255
271
|
name: string;
|
|
256
272
|
key: string;
|
|
257
273
|
session: string;
|
|
@@ -270,15 +286,21 @@ export interface IPlayer {
|
|
|
270
286
|
turnExpiresAt: number | null;
|
|
271
287
|
turnExtensionExpiresAt: number | null;
|
|
272
288
|
hasFlor: boolean;
|
|
273
|
-
|
|
289
|
+
flor: {
|
|
290
|
+
value: number;
|
|
291
|
+
cards: ICard[];
|
|
292
|
+
} | null;
|
|
293
|
+
hasSaidFlor: boolean;
|
|
274
294
|
hasSaidEnvidoPoints: boolean;
|
|
295
|
+
hasSaidTruco: boolean;
|
|
275
296
|
isEnvidoTurn: boolean;
|
|
276
297
|
isOwner: boolean;
|
|
277
298
|
disabled: boolean;
|
|
278
299
|
abandoned: boolean;
|
|
279
300
|
ready: boolean;
|
|
280
301
|
saidEnvidoPoints(): void;
|
|
281
|
-
|
|
302
|
+
saidFlor(): void;
|
|
303
|
+
saidTruco(): void;
|
|
282
304
|
resetCommands(): void;
|
|
283
305
|
calculateEnvido(): Array<{
|
|
284
306
|
value: number;
|
|
@@ -307,6 +329,7 @@ export interface ITeam {
|
|
|
307
329
|
name: string;
|
|
308
330
|
players: Array<IPlayer>;
|
|
309
331
|
points: ITeamPoints;
|
|
332
|
+
setPlayers(players: IPlayer[]): ITeam;
|
|
310
333
|
pointsToWin(matchPoint: number): number;
|
|
311
334
|
getPublicTeam(playerSession?: string): IPublicTeam;
|
|
312
335
|
isTeamDisabled(): boolean;
|
package/dist/types.js
CHANGED
|
@@ -41,9 +41,9 @@ export var EEnvidoAnswerCommand;
|
|
|
41
41
|
})(EEnvidoAnswerCommand || (EEnvidoAnswerCommand = {}));
|
|
42
42
|
export var EEnvidoCommand;
|
|
43
43
|
(function (EEnvidoCommand) {
|
|
44
|
-
EEnvidoCommand["ENVIDO"] = "ENVIDO";
|
|
45
|
-
EEnvidoCommand["REAL_ENVIDO"] = "REAL_ENVIDO";
|
|
46
44
|
EEnvidoCommand["FALTA_ENVIDO"] = "FALTA_ENVIDO";
|
|
45
|
+
EEnvidoCommand["REAL_ENVIDO"] = "REAL_ENVIDO";
|
|
46
|
+
EEnvidoCommand["ENVIDO"] = "ENVIDO";
|
|
47
47
|
})(EEnvidoCommand || (EEnvidoCommand = {}));
|
|
48
48
|
export var EHandState;
|
|
49
49
|
(function (EHandState) {
|
|
@@ -52,6 +52,7 @@ export var EHandState;
|
|
|
52
52
|
EHandState["WAITING_ENVIDO_ANSWER"] = "WAITING_ENVIDO_ANSWER";
|
|
53
53
|
EHandState["WAITING_ENVIDO_POINTS_ANSWER"] = "WAITING_ENVIDO_POINTS_ANSWER";
|
|
54
54
|
EHandState["WAITING_FLOR_ANSWER"] = "WAITING_FLOR_ANSWER";
|
|
55
|
+
EHandState["DISPLAY_FLOR_BATTLE"] = "DISPLAY_FLOR_BATTLE";
|
|
55
56
|
EHandState["BEFORE_FINISHED"] = "BEFORE_FINISHED";
|
|
56
57
|
EHandState["FINISHED"] = "FINISHED";
|
|
57
58
|
})(EHandState || (EHandState = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trucoshi",
|
|
3
|
-
"version": "7.0.0-
|
|
3
|
+
"version": "7.0.0-rc.11",
|
|
4
4
|
"description": "Lightning Truco Server",
|
|
5
5
|
"main": "dist/types.js",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"test:e2e": "prisma db push --force-reset && dotenv -e .env.test -- ts-mocha --exit ./test/**/*.ts -t 60000",
|
|
34
34
|
"profiler": "node --prof ./bin/trucoshi-server",
|
|
35
35
|
"prepublishOnly": "yarn test && yarn build:dist",
|
|
36
|
-
"cli:autoplay": "yarn run ts-node src/
|
|
37
|
-
"cli:play": "yarn run ts-node src/
|
|
36
|
+
"cli:autoplay": "APP_DEBUG_LEVEL=warn yarn run ts-node src/utils/scripts/autoplay",
|
|
37
|
+
"cli:play": "APP_DEBUG_LEVEL=warn yarn run ts-node src/utils/scripts/play",
|
|
38
38
|
"db:push": "prisma db push",
|
|
39
39
|
"db:studio": "prisma studio",
|
|
40
40
|
"db:migrate": "prisma migrate dev"
|
package/dist/server/constants.js
DELETED