trucoshi 1.0.0 → 2.0.1

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.
@@ -1,342 +0,0 @@
1
- import { CARDS } from "./constants";
2
- import { EHandPlayCommand, ICard, IDeck, IHand, IPlayInstance, IMatch, IPlayedCard, IPlayer, IPoints, IRound, ITable, ITeam } from "./types";
3
- import { checkHandWinner, checkMatchWinner, getCardValue, shuffleArray } from "./utils";
4
-
5
- function Deck(): IDeck {
6
- const _deck: IDeck = {
7
- cards: Object.keys(CARDS) as Array<ICard>,
8
- usedCards: [],
9
- takeCard() {
10
- const card = _deck.cards.shift() as ICard
11
- _deck.usedCards.push(card)
12
- return card
13
- },
14
- shuffle() {
15
- _deck.cards = _deck.cards.concat(_deck.usedCards)
16
- _deck.usedCards = []
17
- _deck.cards = shuffleArray(_deck.cards)
18
- if (_deck.cards.length !== 40) {
19
- throw new Error("This is not good")
20
- }
21
- return _deck
22
- }
23
- }
24
- return _deck
25
- }
26
-
27
- function Table(teams: Array<ITeam>, size: number): ITable {
28
- const _table: ITable = {
29
- players: [],
30
- cards: [],
31
- forehandIdx: 0,
32
- nextTurn() {
33
- if (_table.forehandIdx < (size * 2) - 1) {
34
- _table.forehandIdx++
35
- } else {
36
- _table.forehandIdx = 0
37
- }
38
- return _table.player()
39
- },
40
- getPlayerPosition(id: string) {
41
- return _table.players.findIndex(p => p.id === id)
42
- },
43
- player(idx?: number) {
44
- if (idx !== undefined) {
45
- return _table.players[idx]
46
- }
47
- return _table.players[_table.forehandIdx]
48
- }
49
- }
50
-
51
- if (teams[0].players.length != size || teams[1].players.length != size) {
52
- throw new Error("Unexpected team size")
53
- }
54
-
55
- for (let i = 0; i < size; i++) {
56
- _table.players.push(teams[0].players[i])
57
- _table.players.push(teams[1].players[i])
58
- }
59
-
60
- return _table;
61
- }
62
-
63
- function Round(): IRound {
64
- const _round: IRound = {
65
- highest: -1,
66
- winner: null,
67
- cards: [],
68
- tie: false,
69
- play({ card, player }: IPlayedCard) {
70
- const value = getCardValue(card)
71
- if (_round.highest > -1 && value === _round.highest) {
72
- _round.tie = true
73
- }
74
- if (value > _round.highest) {
75
- _round.tie = false
76
- _round.highest = value
77
- _round.winner = player
78
- }
79
- _round.cards.push({ card, player })
80
- return card;
81
- }
82
- }
83
-
84
- return _round
85
- }
86
-
87
- export function Match(teams: Array<ITeam> = [], matchPoint: number = 9): IMatch {
88
-
89
- const deck = Deck().shuffle()
90
-
91
- const size = teams[0].players.length
92
-
93
- if (size !== teams[1].players.length) {
94
- throw new Error("Team size mismatch")
95
- }
96
-
97
- function* handsGeneratorSequence() {
98
- while (!_match.winner) {
99
- deck.shuffle()
100
- const hand = _match.setCurrentHand(Hand(_match, deck, _match.hands.length + 1)) as IHand
101
- _match.pushHand(hand)
102
- while(!hand.finished) {
103
- const { value } = hand.getNextPlayer()
104
- if (value && value.finished) {
105
- continue;
106
- }
107
- _match.setCurrentHand(value as IHand)
108
- yield _match
109
- }
110
-
111
- _match.addPoints(hand.points)
112
- _match.setCurrentHand(null)
113
-
114
- const hasWinner = checkMatchWinner(teams, matchPoint)
115
-
116
- if (hasWinner !== null) {
117
- _match.setWinner(hasWinner)
118
- _match.setCurrentHand(null)
119
- }
120
- _match.table.nextTurn()
121
- }
122
- yield _match
123
- }
124
-
125
- const handsGenerator = handsGeneratorSequence()
126
-
127
- const _match: IMatch = {
128
- winner: null,
129
- teams: teams as [ITeam, ITeam],
130
- hands: [],
131
- table: Table(teams, size),
132
- currentHand: null,
133
- play() {
134
- _match.getNextTurn()
135
- if (!_match.currentHand) {
136
- return;
137
- }
138
- return _match.currentHand.play()
139
- },
140
- addPoints(points: IPoints) {
141
- _match.teams[0].addPoints(points[0])
142
- _match.teams[1].addPoints(points[1])
143
- },
144
- pushHand(hand: IHand) {
145
- _match.hands.push(hand)
146
- },
147
- setCurrentHand(hand: IHand) {
148
- _match.currentHand = hand
149
- return _match.currentHand
150
- },
151
- setWinner(winner: ITeam) {
152
- _match.winner = winner
153
- },
154
- getNextTurn() {
155
- return handsGenerator.next()
156
- }
157
- }
158
-
159
- return _match;
160
- }
161
-
162
- function PlayInstance(hand: IHand) {
163
-
164
- const _instance: IPlayInstance = {
165
- handIdx: hand.idx,
166
- roundIdx: hand.rounds.length,
167
- player: hand.currentPlayer,
168
- commands: [],
169
- rounds: hand.rounds,
170
- use(idx: number) {
171
- const player = hand.currentPlayer
172
- const round = hand.currentRound
173
- if (!player || !round) {
174
- return null
175
- }
176
-
177
- const card = player.useCard(idx)
178
- if (card) {
179
- return round.play({ player, card })
180
- }
181
-
182
- return null
183
- },
184
- say(command: EHandPlayCommand) {
185
- if (!hand.currentPlayer) {
186
- return null
187
- }
188
- return hand
189
- }
190
- }
191
-
192
- return _instance
193
- }
194
-
195
- function Hand(match: IMatch, deck: IDeck, idx: number) {
196
-
197
- const truco = 1;
198
-
199
- match.teams.forEach((team) => {
200
- team.players.forEach(player => {
201
- const playerHand = [deck.takeCard(), deck.takeCard(), deck.takeCard()]
202
- player.setHand(playerHand)
203
- // player.setHand(["5c", "4c", "6c"])
204
- })
205
- })
206
-
207
- function* roundsGeneratorSequence() {
208
- let currentRoundIdx = 0;
209
- let forehandTeamIdx = match.table.player(_hand.turn).teamIdx as 0 | 1
210
-
211
- while (currentRoundIdx < 3 && !_hand.finished) {
212
-
213
- let i = 0
214
-
215
- const round = Round()
216
- _hand.setCurrentRound(round)
217
- _hand.pushRound(round)
218
-
219
- let previousRound = _hand.rounds[currentRoundIdx - 1]
220
-
221
- // Put previous round winner as forehand
222
- if (previousRound && previousRound.winner && !previousRound.tie) {
223
- const newTurn = match.table.getPlayerPosition(previousRound.winner.id)
224
- if (newTurn !== -1) {
225
- _hand.setTurn(newTurn)
226
- }
227
- }
228
-
229
- while (i < match.table.players.length) {
230
- _hand.setCurrentPlayer(match.table.player(_hand.turn))
231
-
232
- if (_hand.turn >= match.table.players.length - 1) {
233
- _hand.setTurn(0)
234
- } else {
235
- _hand.setTurn(_hand.turn + 1)
236
- }
237
-
238
- i++
239
-
240
- yield _hand;
241
- }
242
-
243
- const teamIdx = checkHandWinner(_hand.rounds, forehandTeamIdx)
244
-
245
- if (teamIdx !== null) {
246
- _hand.addPoints(teamIdx, truco)
247
- _hand.setFinished(true)
248
- }
249
- currentRoundIdx++;
250
- }
251
- yield _hand
252
- }
253
-
254
- const roundsGenerator = roundsGeneratorSequence()
255
-
256
- const _hand: IHand = {
257
- idx,
258
- turn: Number(match.table.forehandIdx),
259
- rounds: [],
260
- finished: false,
261
- points: {
262
- 0: 0,
263
- 1: 0
264
- },
265
- currentRound: null,
266
- currentPlayer: null,
267
- play() {
268
- return PlayInstance(_hand)
269
- },
270
- pushRound(round: IRound) {
271
- _hand.rounds.push(round)
272
- return round
273
- },
274
- setTurn(turn: number) {
275
- _hand.turn = turn
276
- return match.table.player(_hand.turn)
277
- },
278
- addPoints(team: 0 | 1, points: number) {
279
- _hand.points[team] = _hand.points[team] + points
280
- },
281
- setCurrentRound(round: IRound | null) {
282
- _hand.currentRound = round
283
- return _hand.currentRound
284
- },
285
- setCurrentPlayer(player: IPlayer | null) {
286
- _hand.currentPlayer = player
287
- return _hand.currentPlayer
288
- },
289
- setFinished(finshed: boolean) {
290
- _hand.finished = finshed
291
- return _hand.finished
292
- },
293
- getNextPlayer() {
294
- return roundsGenerator.next();
295
- },
296
- }
297
-
298
- return _hand
299
- }
300
-
301
- export function Player(id: string, teamIdx: number) {
302
- const _player: IPlayer = {
303
- id,
304
- teamIdx,
305
- hand: [],
306
- usedHand: [],
307
- setHand(hand: Array<ICard>) {
308
- _player.hand = hand
309
- _player.usedHand = []
310
- return hand
311
- },
312
- useCard(idx: number) {
313
- if (_player.hand[idx]) {
314
- const card = _player.hand.splice(idx, 1)[0]
315
- _player.usedHand.push(card)
316
- return card;
317
- }
318
- return null
319
- }
320
- }
321
-
322
- return _player;
323
- }
324
-
325
- export function Team(color: string, players: Array<IPlayer>) {
326
- const _team = {
327
- _players: new Map<string, IPlayer>(),
328
- get players() {
329
- return Array.from(_team._players.values())
330
- },
331
- color,
332
- points: 0,
333
- addPoints(points: number) {
334
- _team.points += points
335
- return _team.points
336
- },
337
- }
338
-
339
- players.forEach(player => _team._players.set(player.id, player))
340
-
341
- return _team;
342
- }
package/src/lib/types.ts DELETED
@@ -1,110 +0,0 @@
1
- import { CARDS } from "./constants"
2
-
3
- export type ICard = keyof typeof CARDS
4
-
5
- export interface IDeck {
6
- cards: Array<ICard>
7
- usedCards: Array<ICard>
8
- takeCard(): ICard
9
- shuffle(): IDeck
10
- }
11
-
12
- export interface IPlayedCard {
13
- player: IPlayer
14
- card: ICard
15
- }
16
-
17
- export interface IPlayer {
18
- teamIdx: number
19
- id: string
20
- hand: Array<ICard>,
21
- usedHand: Array<ICard>
22
- setHand(hand: Array<ICard>): Array<ICard>
23
- useCard(idx: number): ICard | null
24
- }
25
-
26
- export interface ITeam {
27
- color: string
28
- _players: Map<string, IPlayer>
29
- players: Array<IPlayer>
30
- points: number
31
- addPoints(points: number): number
32
- }
33
-
34
- export interface IMatch {
35
- teams: [ITeam, ITeam]
36
- hands: Array<IHand>
37
- winner: ITeam | null
38
- currentHand: IHand | null
39
- table: ITable
40
- play(): IPlayInstance | undefined
41
- addPoints(points: IPoints): void
42
- pushHand(hand: IHand): void
43
- setCurrentHand(hand: IHand | null): IHand | null
44
- setWinner(winner: ITeam): void
45
- getNextTurn(): IteratorResult<IMatch | null, IMatch | null | void>
46
- }
47
-
48
- export type IPoints = {
49
- 0: number // team 0
50
- 1: number // team 1
51
- 2?: number // number of tied rounds
52
- }
53
-
54
- export type IGetNextPlayerResult = { currentPlayer?: IPlayer, currentRound?: IRound, points?: IPoints }
55
-
56
- export enum EHandPlayCommand {
57
- TRUCO,
58
- ENVIDO,
59
- ENVIDO_ENVIDO,
60
- REAL_ENVIDO,
61
- FALTA_ENVIDO,
62
- MAZO,
63
- FLOR,
64
- CONTRAFLOR,
65
- }
66
-
67
- export interface IPlayInstance {
68
- handIdx: number
69
- roundIdx: number
70
- player: IPlayer | null
71
- commands: Array<EHandPlayCommand> | null
72
- rounds: Array<IRound> | null
73
- use(idx: number): ICard | null
74
- say(command: EHandPlayCommand): IHand | null
75
- }
76
-
77
- export interface IHand {
78
- idx: number
79
- turn: number
80
- finished: boolean
81
- points: IPoints
82
- rounds: Array<IRound>
83
- currentPlayer: IPlayer | null
84
- currentRound: IRound | null
85
- play(): IPlayInstance
86
- pushRound(round: IRound): IRound
87
- setTurn(turn: number): IPlayer
88
- addPoints(team: 0 | 1, points: number): void
89
- setCurrentRound(round: IRound | null): IRound | null
90
- setCurrentPlayer(player: IPlayer | null): IPlayer | null
91
- setFinished(finshed: boolean): boolean
92
- getNextPlayer(): IteratorResult<IHand, IHand | void>
93
- }
94
-
95
- export interface ITable {
96
- forehandIdx: number,
97
- cards: Array<Array<IPlayedCard>>,
98
- players: Array<IPlayer>,
99
- nextTurn(): IPlayer,
100
- player(idx?: number): IPlayer,
101
- getPlayerPosition(id: string): number
102
- }
103
-
104
- export interface IRound {
105
- tie: boolean,
106
- winner: IPlayer | null
107
- highest: number
108
- cards: Array<IPlayedCard>
109
- play(playedCard: IPlayedCard): ICard
110
- }
package/src/lib/utils.ts DELETED
@@ -1,69 +0,0 @@
1
- import { CARDS } from "./constants";
2
- import { ICard, IPoints, IRound, ITeam } from "./types";
3
-
4
- export function getCardValue(card: ICard) {
5
- return CARDS[card] || -1
6
- }
7
-
8
- export function shuffleArray<T = never>(array: Array<T>) {
9
- let currentIndex = array.length, randomIndex;
10
-
11
- while (currentIndex != 0) {
12
- randomIndex = Math.floor(Math.random() * currentIndex);
13
- currentIndex--;
14
- [array[currentIndex], array[randomIndex]] = [
15
- array[randomIndex], array[currentIndex]];
16
- }
17
-
18
- return array as Array<T>;
19
- }
20
-
21
- export function checkHandWinner(rounds: Array<IRound>, forehandTeamIdx: 0 | 1): null | 0 | 1 {
22
- const roundsWon: IPoints = {
23
- 0: 0,
24
- 1: 0,
25
- 2: 0 // tied rounds
26
- }
27
-
28
- for (let i = 0; i < rounds.length; i++) {
29
- const round = rounds[i];
30
- if (round.tie) {
31
- roundsWon[0] += 1;
32
- roundsWon[1] += 1;
33
- roundsWon[2] = (roundsWon[2] || 0) + 1;
34
- continue;
35
- }
36
- if (round.winner?.teamIdx === 0) {
37
- roundsWon[0] += 1;
38
- }
39
- if (round.winner?.teamIdx === 1) {
40
- roundsWon[1] += 1;
41
- }
42
- }
43
-
44
- const ties = roundsWon[2] || 0
45
-
46
- if ((roundsWon[0] > 2 && roundsWon[1] > 2) || (rounds.length > 2 && ties > 0)) {
47
- return forehandTeamIdx
48
- }
49
-
50
- if (roundsWon[0] >= 2 && roundsWon[1] < 2) {
51
- return 0
52
- }
53
-
54
- if (roundsWon[1] >= 2 && roundsWon[0] < 2) {
55
- return 1
56
- }
57
-
58
- return null
59
- }
60
-
61
- export function checkMatchWinner(teams: Array<ITeam>, matchPoint: number): ITeam | null {
62
- if (teams[0].points >= matchPoint) {
63
- return teams[0]
64
- }
65
- if (teams[1].points >= matchPoint) {
66
- return teams[1]
67
- }
68
- return null
69
- }
@@ -1,22 +0,0 @@
1
- import { createServer } from "http";
2
- import { Server } from "socket.io";
3
-
4
- const PORT = 4001
5
-
6
- const httpServer = createServer();
7
- const io = new Server(httpServer, {
8
- cors: {
9
- origin: "http://localhost:3000",
10
- methods: ["GET", "POST"]
11
- }
12
- });
13
-
14
- io.on("connection", (socket) => {
15
- socket.on('ping', (msg) => {
16
- io.emit('pong', msg);
17
- });
18
- });
19
-
20
- httpServer.listen(PORT);
21
-
22
- console.log('Listening on port', PORT)
File without changes
@@ -1,41 +0,0 @@
1
- import { COLORS } from '../lib/constants';
2
- import { Match, Player, Team } from "../lib/trucoshi";
3
- import { ICard, IRound } from '../lib/types';
4
-
5
- (async () => {
6
- const player1 = Player('lukini', 0)
7
- const player2 = Player('guada', 0)
8
- const player3 = Player('denoph', 1)
9
- const player4 = Player('juli', 1)
10
- const player5 = Player('fran', 1)
11
- const player6 = Player('day', 0)
12
-
13
- const team1 = Team(COLORS[0], [player1, player2, player6])
14
- const team2 = Team(COLORS[1], [player3, player4, player5])
15
-
16
- const match = Match([team1, team2], 9);
17
-
18
- while(!match.winner) {
19
- const play = match.play()
20
-
21
- if (!play || !play.player) {
22
- break;
23
- }
24
-
25
- const name = play.player.id.toUpperCase()
26
- console.log(`=== Mano ${play.handIdx} === Ronda ${play.roundIdx} === Turno de ${name} ===`)
27
- match.teams.map((team, id) => console.log(`=== Team ${id} = ${team.points} Puntos ===`))
28
- console.log(play.rounds && play.rounds.length ? (play.rounds.map((round: IRound) => round.cards.length ? round.cards.map(c => [c.player.id, c.card]) : '')) : '')
29
-
30
- const randomIdx = Math.round(Math.random() * (play.player.hand.length - 1))
31
- const card = play.use(randomIdx)
32
-
33
- console.log(`\n${JSON.stringify(play.player.hand)}\nUsing ${card}`)
34
- console.log(play.rounds && play.rounds.length ? (play.rounds.map((round: IRound) => round.cards.length ? round.cards.map(c => [c.player.id, c.card]) : '')) : '')
35
- }
36
-
37
- console.log('\n')
38
- match.teams.map((t, i) => console.log(`Equipo ${i}: ${t.players.map(p => ` ${p.id}`)} === ${t.points} puntos`))
39
- console.log(`\nEquipo Ganador:${match.winner?.players.map(p => ` ${p.id}`)}`)
40
-
41
- })();
@@ -1,68 +0,0 @@
1
- import * as readline from 'readline'
2
- import { COLORS } from '../lib/constants';
3
- import { Match, Player, Team } from "../lib/trucoshi";
4
- import { ICard, IPlayer, IRound } from '../lib/types';
5
-
6
- (async () => {
7
- const player1 = Player('lukini', 0)
8
- const player2 = Player('guada', 0)
9
- const player3 = Player('denoph', 1)
10
- const player4 = Player('juli', 1)
11
-
12
- const team1 = Team(COLORS[0], [player1, player2])
13
- const team2 = Team(COLORS[1], [player3, player4])
14
-
15
- const match = Match([team1, team2], 9);
16
-
17
- while(!match.winner) {
18
- if (match.currentHand?.finished) {
19
- console.log(match.currentHand && match.currentHand.rounds.length ? (match.currentHand.rounds.map((round: IRound) => round.cards.length ? round.cards.map(c => [c.player.id, c.card]) : '')) : '')
20
- }
21
- const { value } = match.getNextTurn()
22
- if (value && value.currentHand && value.currentHand.currentPlayer) {
23
- // const card = value.currentPlayer.useCard(Math.round(Math.random() * 2))
24
- // value.currentRound?.play({ card, player: value.currentPlayer })
25
- const prom = () => new Promise<void>((resolve) => {
26
-
27
- // process.stdout.write('\u001B[2J\u001B[0;0f');
28
- const rl = readline.createInterface(process.stdin, process.stdout);
29
-
30
- const currentHand: any = value.currentHand;
31
- const name = value.currentHand?.currentPlayer?.id.toUpperCase()
32
-
33
- console.log(`=== Mano ${currentHand.idx + 1} === Ronda ${currentHand.rounds.length} === Turno de ${name} ===\n`)
34
-
35
- match.teams.map((team, id) => console.log(`=== Team ${id} = ${team.points} Puntos ===\n`))
36
-
37
- console.log(currentHand && currentHand.rounds.length ? (currentHand.rounds.map((round: IRound) => round.cards.length ? round.cards.map(c => [c.player.id, c.card]) : '')) : '')
38
-
39
- rl.setPrompt(`\n${name} elije una carta [1, 2, 3]: ${JSON.stringify(value.currentHand?.currentPlayer?.hand)}\n`);
40
- rl.prompt();
41
- rl.on('line', (idx: string) => {
42
- const index = Number(idx) - 1
43
- let playedCard: ICard | null | undefined = null
44
- if (index >= 0 && index < 3) {
45
- playedCard = value.currentHand?.currentPlayer?.useCard(index)
46
- }
47
- if (!playedCard) {
48
- rl.close();
49
- return (async () => {
50
- await prom()
51
- resolve()
52
- })();
53
- }
54
- value.currentHand?.currentRound?.play({ player: value.currentHand?.currentPlayer as IPlayer, card: playedCard as ICard })
55
- console.log(currentHand && currentHand.rounds.length ? (currentHand.rounds.map((round: IRound) => round.cards.length ? round.cards.map(c => [c.player.id, c.card]) : '')) : '')
56
- rl.close();
57
- resolve()
58
- });
59
- });
60
-
61
- await prom()
62
- }
63
-
64
- }
65
-
66
- console.log(match.teams.map(t => [t.points, t.players[0].id]))
67
-
68
- })();