Skip to content

Commit

Permalink
add createRound
Browse files Browse the repository at this point in the history
Co-authored-by: 賴鴻德 <[email protected]>
Co-authored-by: miku3920 <[email protected]>
Co-authored-by: Tuhacrt <[email protected]>
Co-authored-by: leave3310 <[email protected]>
Co-authored-by: kuannnn <[email protected]>
  • Loading branch information
6 people committed Oct 29, 2023
1 parent 03a4001 commit 433451f
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 1 deletion.
253 changes: 253 additions & 0 deletions packages/domain_layer/src/round/createRound.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import { pipe } from 'fp-ts/lib/function';
import { prop } from 'remeda';
import O from 'fp-ts/lib/Option';
import { createGame, createIdToGame } from 'game';
import { Player } from 'player';

import { createRound } from './createRound';
import { SelectedPlayerState } from './type';

describe('createRound', () => {
it(`
given game
rounds is empty array # no started round
when create round
then return round
currentPlayer is random
`, () => {
const players: Player[] = [
{ id: '1', uid: '1', name: '1', hands: [], pastReceivedCards: [] },
{ id: '2', uid: '2', name: '2', hands: [], pastReceivedCards: [] },
];
const game = pipe(
//
createGame(players),
createIdToGame,
);

const round = pipe(
//
game,
O.map(createRound),
);

expect(round).toMatchObject(
O.some({
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
);

const currentPlayer = pipe(
round,
O.map(prop('currentPlayer')),
O.toUndefined,
);

const currentPlayerIsInPlayers = players.some(
(player) => player.id === currentPlayer.id,
);

expect(currentPlayerIsInPlayers).toBe(true);
});

it(`
given game
rounds array has one round
prevRound's selectedPlayer.state is GUESS_CARD_WIN
when create round
then return round
currentPlayer is preRound's currentPlayer
`, () => {
const players: Player[] = [
{ id: '1', uid: '1', name: '1', hands: [], pastReceivedCards: [] },
{ id: '2', uid: '2', name: '2', hands: [], pastReceivedCards: [] },
];

const game = pipe(
//
createGame(players),
createIdToGame,
);

const round = pipe(
//
game,
O.map((game) => ({
...game,
rounds: [
{
id: '1',
currentPlayer: game.players[0],
selectedPlayer: game.players[1],
state: SelectedPlayerState.GUESS_CARD_WIN,
},
],
})),
O.map(createRound),
);

expect(round).toMatchObject(
O.some({
currentPlayer: pipe(
game,
O.map(prop('players')),
O.map(prop(0)),
O.toUndefined,
),
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
);
});

it(`
given game
rounds array has one round
prevRound's selectedPlayer.state is GUESS_CARD_LOSS
when create round
then return round
currentPlayer is preRound's selectedPlayer
`, () => {
const players: Player[] = [
{ id: '1', uid: '1', name: '1', hands: [], pastReceivedCards: [] },
{ id: '2', uid: '2', name: '2', hands: [], pastReceivedCards: [] },
];

const game = pipe(
//
createGame(players),
createIdToGame,
);

const round = pipe(
//
game,
O.map((game) => ({
...game,
rounds: [
{
id: '1',
currentPlayer: game.players[0],
selectedPlayer: game.players[1],
state: SelectedPlayerState.GUESS_CARD_LOSS,
},
],
})),
O.map(createRound),
);

expect(round).toMatchObject(
O.some({
currentPlayer: pipe(
game,
O.map(prop('players')),
O.map(prop(1)),
O.toUndefined,
),
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
);
});

it(`
given game
rounds array has one round
prevRound's selectedPlayer.state is EVADE_LOOK_CARD
when create round
then return round
currentPlayer is preRound's selectedPlayer
`, () => {
const players: Player[] = [
{ id: '1', uid: '1', name: '1', hands: [], pastReceivedCards: [] },
{ id: '2', uid: '2', name: '2', hands: [], pastReceivedCards: [] },
];

const game = pipe(
//
createGame(players),
createIdToGame,
);

const round = pipe(
//
game,
O.map((game) => ({
...game,
rounds: [
{
id: '1',
currentPlayer: game.players[0],
selectedPlayer: game.players[1],
state: SelectedPlayerState.EVADE_LOOK_CARD,
},
],
})),
O.map(createRound),
);

expect(round).toMatchObject(
O.some({
currentPlayer: pipe(
game,
O.map(prop('players')),
O.map(prop(1)),
O.toUndefined,
),
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
);
});

it(`
given game
rounds array has one round
prevRound's selectedPlayer.state is EVADE_NOT_LOOK_CARD
when create round
then return round
currentPlayer is preRound's selectedPlayer
`, () => {
const players: Player[] = [
{ id: '1', uid: '1', name: '1', hands: [], pastReceivedCards: [] },
{ id: '2', uid: '2', name: '2', hands: [], pastReceivedCards: [] },
];

const game = pipe(
//
createGame(players),
createIdToGame,
);

const round = pipe(
//
game,
O.map((game) => ({
...game,
rounds: [
{
id: '1',
currentPlayer: game.players[0],
selectedPlayer: game.players[1],
state: SelectedPlayerState.EVADE_NOT_LOOK_CARD,
},
],
})),
O.map(createRound),
);

expect(round).toMatchObject(
O.some({
currentPlayer: pipe(
game,
O.map(prop('players')),
O.map(prop(1)),
O.toUndefined,
),
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
);
});
});
41 changes: 41 additions & 0 deletions packages/domain_layer/src/round/createRound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Game } from 'game';
import { pipe } from 'fp-ts/function';
import { prop } from 'remeda';
import { ReadonlyNonEmptyArray } from 'fp-ts/ReadonlyNonEmptyArray';
import { Player } from 'player';
import A from 'fp-ts/Array';
import Random from 'fp-ts/Random';
import O from 'fp-ts/Option';
import { always } from 'utils/fp';

import { OmitIdRound, SelectedPlayerState } from './type';

interface CreateRound {
(game: Game): OmitIdRound;
}

export const createRound: CreateRound = (game) =>
pipe(
//
game,
prop('rounds'),
A.last,
O.match(
always({
currentPlayer: pipe(
game.players as unknown as ReadonlyNonEmptyArray<Player>,
Random.randomElem,
)(),
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
(prevRound) => ({
currentPlayer:
prevRound.state === SelectedPlayerState.GUESS_CARD_WIN
? prevRound.currentPlayer
: prevRound.selectedPlayer,
selectedPlayer: null,
state: SelectedPlayerState.NONE,
}),
),
);
15 changes: 14 additions & 1 deletion packages/domain_layer/src/round/type.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { Player } from 'player';

export enum SelectedPlayerState {
'NONE',
'GUESS_CARD_ING',
'GUESS_CARD_LOSS',
'GUESS_CARD_WIN',
'EVADE_ING',
'EVADE_LOOK_CARD',
'EVADE_NOT_LOOK_CARD',
}

export type Round = {
id: string;
currentPlayer: Player;
selectedPlayer: Player;
selectedPlayer?: Player;
state: SelectedPlayerState;
};

export type OmitIdRound = Omit<Round, 'id'>;

0 comments on commit 433451f

Please sign in to comment.