Skip to content

Commit 43dcaac

Browse files
committed
write turn / phase stats in ctx.stats
currently contains numMoves, an object that tracks the number of moves made by each player in the current turn / phase.
1 parent 84f07c6 commit 43dcaac

3 files changed

Lines changed: 92 additions & 44 deletions

File tree

src/core/flow.js

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,9 @@ export function FlowWithPhases({
335335

336336
const shouldEndTurn = ({ G, ctx }) => {
337337
const conf = phaseMap[ctx.phase];
338-
if (conf.movesPerTurn && ctx.currentPlayerMoves >= conf.movesPerTurn) {
338+
339+
const currentPlayerMoves = ctx.stats.turn.numMoves[ctx.currentPlayer] || 0;
340+
if (conf.movesPerTurn && currentPlayerMoves >= conf.movesPerTurn) {
339341
return true;
340342
}
341343
return conf.endTurnIf(G, ctx);
@@ -345,8 +347,19 @@ export function FlowWithPhases({
345347
const startPhase = function(state, config) {
346348
const G = config.onPhaseBegin(state.G, state.ctx);
347349
const ctx = InitTurnOrderState(state.G, state.ctx, config.turnOrder);
350+
351+
// Reset stats.
352+
ctx.stats = {
353+
...ctx.stats,
354+
phase: {
355+
...ctx.stats.phase,
356+
numMoves: {},
357+
allPlayed: false,
358+
},
359+
};
360+
348361
const allowedMoves = config.allowedMoves(G, ctx);
349-
return { ...state, G, ctx: { ...ctx, allowedMoves, _played: [] } };
362+
return { ...state, G, ctx: { ...ctx, allowedMoves } };
350363
};
351364

352365
const startTurn = function(state, config) {
@@ -360,6 +373,16 @@ export function FlowWithPhases({
360373
const ctx = { ...state.ctx };
361374
ctx.allowedMoves = config.allowedMoves(G, ctx);
362375

376+
// Reset stats.
377+
ctx.stats = {
378+
...ctx.stats,
379+
turn: {
380+
...ctx.stats.turn,
381+
numMoves: {},
382+
allPlayed: false,
383+
},
384+
};
385+
363386
return { ...state, G, ctx, _undo, _redo: [] };
364387
};
365388

@@ -446,7 +469,8 @@ export function FlowWithPhases({
446469
const conf = phaseMap[ctx.phase];
447470

448471
// Prevent ending the turn if movesPerTurn haven't been made.
449-
if (conf.movesPerTurn && ctx.currentPlayerMoves < conf.movesPerTurn) {
472+
const currentPlayerMoves = ctx.stats.turn.numMoves[ctx.currentPlayer] || 0;
473+
if (conf.movesPerTurn && currentPlayerMoves < conf.movesPerTurn) {
450474
return state;
451475
}
452476

@@ -477,11 +501,7 @@ export function FlowWithPhases({
477501
const turn = ctx.turn + 1;
478502

479503
// Update state.
480-
ctx = {
481-
...ctx,
482-
turn,
483-
currentPlayerMoves: 0,
484-
};
504+
ctx = { ...ctx, turn };
485505

486506
// End phase if condition is met.
487507
const endPhaseArg = shouldEndPhase(state);
@@ -507,15 +527,26 @@ export function FlowWithPhases({
507527
return { ...state, ctx: { ...state.ctx, gameover: arg } };
508528
}
509529

530+
function updateStats(state, key, playerID) {
531+
const moves = (state.ctx.stats[key].numMoves[playerID] || 0) + 1;
532+
const numMoves = { ...state.ctx.stats[key].numMoves, [playerID]: moves };
533+
const t = { ...state.ctx.stats[key], numMoves };
534+
535+
if (Object.keys(numMoves).length == state.ctx.numPlayers) {
536+
t.allPlayed = true;
537+
}
538+
539+
const stats = { ...state.ctx.stats, [key]: t };
540+
const ctx = { ...state.ctx, stats };
541+
542+
return { ...state, ctx };
543+
}
544+
510545
function processMove(state, action, dispatch) {
511546
let conf = phaseMap[state.ctx.phase];
512547

513-
const currentPlayerMoves = state.ctx.currentPlayerMoves + 1;
514-
let _played = state.ctx._played;
515-
if (!_played.includes(action.playerID)) {
516-
_played = [..._played, action.playerID];
517-
}
518-
const allPlayed = _played.length == state.ctx.numPlayers;
548+
state = updateStats(state, 'turn', action.playerID);
549+
state = updateStats(state, 'phase', action.playerID);
519550

520551
// Update actionPlayers if _actionPlayersOnce is set.
521552
let actionPlayers = state.ctx.actionPlayers;
@@ -529,9 +560,6 @@ export function FlowWithPhases({
529560
ctx: {
530561
...state.ctx,
531562
actionPlayers,
532-
currentPlayerMoves,
533-
_played,
534-
allPlayed,
535563
},
536564
};
537565

@@ -625,7 +653,7 @@ export function FlowWithPhases({
625653
currentPlayerMoves: 0,
626654
playOrder: Array.from(Array(numPlayers), (d, i) => i + ''),
627655
playOrderPos: 0,
628-
_played: [],
656+
stats: { turn: { numMoves: {} }, phase: { numMoves: {} } },
629657
allPlayed: false,
630658
phase: phases[0].name,
631659
}),

src/core/flow.test.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ test('movesPerTurn', () => {
5656
let flow = FlowWithPhases({ movesPerTurn: 2 });
5757
let state = { ctx: flow.ctx(2) };
5858
expect(state.ctx.turn).toBe(0);
59-
state = flow.processMove(state, makeMove().payload);
59+
state = flow.processMove(state, makeMove('move', null, '0').payload);
6060
expect(state.ctx.turn).toBe(0);
6161
state = flow.processGameEvent(state, gameEvent('endTurn'));
6262
expect(state.ctx.turn).toBe(0);
63-
state = flow.processMove(state, makeMove().payload);
63+
state = flow.processMove(state, makeMove('move', null, '0').payload);
6464
expect(state.ctx.turn).toBe(1);
6565
}
6666

@@ -71,17 +71,17 @@ test('movesPerTurn', () => {
7171
});
7272
let state = { ctx: flow.ctx(2) };
7373
expect(state.ctx.turn).toBe(0);
74-
state = flow.processMove(state, makeMove().payload);
74+
state = flow.processMove(state, makeMove('move', null, '0').payload);
7575
expect(state.ctx.turn).toBe(0);
7676
state = flow.processGameEvent(state, gameEvent('endTurn'));
7777
expect(state.ctx.turn).toBe(0);
78-
state = flow.processMove(state, makeMove().payload);
78+
state = flow.processMove(state, makeMove('move', null, '0').payload);
7979
expect(state.ctx.turn).toBe(1);
8080

8181
state = flow.processGameEvent(state, gameEvent('endPhase'));
8282

8383
expect(state.ctx.turn).toBe(1);
84-
state = flow.processMove(state, makeMove().payload);
84+
state = flow.processMove(state, makeMove('move', null, '1').payload);
8585
expect(state.ctx.turn).toBe(2);
8686
}
8787
});
@@ -756,7 +756,7 @@ test('endTurn is not called twice in one move', () => {
756756
expect(state.ctx.turn).toBe(2);
757757
});
758758

759-
test('played / allPlayed', () => {
759+
test('allPlayed', () => {
760760
let game = Game({
761761
moves: { A: () => ({ A: true }) },
762762
});
@@ -767,10 +767,8 @@ test('played / allPlayed', () => {
767767

768768
state = reducer(state, makeMove('A', null, '0'));
769769
state = reducer(state, gameEvent('endTurn', null, '0'));
770-
expect(state.ctx.allPlayed).toBe(false);
771-
expect(state.ctx._played).toEqual(['0']);
770+
expect(state.ctx.stats.phase.allPlayed).toBe(false);
772771
state = reducer(state, makeMove('A', null, '1'));
773772
state = reducer(state, gameEvent('endTurn', null, '1'));
774-
expect(state.ctx.allPlayed).toBe(true);
775-
expect(state.ctx._played).toEqual(['0', '1']);
773+
expect(state.ctx.stats.phase.allPlayed).toBe(true);
776774
});

src/server/index.test.js

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -183,33 +183,39 @@ test('action', async () => {
183183
G: {},
184184
ctx: {
185185
_random: { seed: 0 },
186+
actionPlayers: ['0'],
187+
allPlayed: false,
186188
allowedMoves: null,
187189
currentPlayer: '0',
188-
actionPlayers: ['0'],
189190
currentPlayerMoves: 0,
190-
allPlayed: false,
191-
_played: [],
192191
numPlayers: 2,
193192
phase: 'default',
194-
turn: 0,
195193
playOrder: ['0', '1'],
196194
playOrderPos: 0,
195+
stats: {
196+
phase: { allPlayed: false, numMoves: {} },
197+
turn: { numMoves: {} },
198+
},
199+
turn: 0,
197200
},
198201
},
199202
],
200203
ctx: {
201204
_random: { seed: 0 },
205+
actionPlayers: ['0'],
206+
allPlayed: false,
202207
allowedMoves: null,
203208
currentPlayer: '0',
204-
actionPlayers: ['0'],
205209
currentPlayerMoves: 0,
206-
allPlayed: false,
207-
_played: [],
208210
numPlayers: 2,
209211
phase: 'default',
210-
turn: 0,
211212
playOrder: ['0', '1'],
212213
playOrderPos: 0,
214+
stats: {
215+
phase: { allPlayed: false, numMoves: {} },
216+
turn: { allPlayed: false, numMoves: {} },
217+
},
218+
turn: 0,
213219
},
214220
log: [],
215221
},
@@ -220,35 +226,51 @@ test('action', async () => {
220226
G: {},
221227
ctx: {
222228
_random: { seed: 0 },
229+
actionPlayers: ['1'],
230+
allPlayed: false,
223231
allowedMoves: null,
224232
currentPlayer: '1',
225-
actionPlayers: ['1'],
226233
currentPlayerMoves: 0,
227-
allPlayed: false,
228-
_played: [],
229234
numPlayers: 2,
230235
phase: 'default',
231-
turn: 1,
232236
playOrder: ['0', '1'],
233237
playOrderPos: 1,
238+
stats: {
239+
phase: { allPlayed: false, numMoves: {} },
240+
turn: { allPlayed: false, numMoves: {} },
241+
},
242+
turn: 1,
234243
},
235244
},
236245
],
237246
ctx: {
238247
_random: undefined,
239-
allowedMoves: null,
240-
currentPlayer: '1',
241248
actionPlayers: ['1'],
242249
allPlayed: false,
243-
_played: [],
250+
allowedMoves: null,
251+
currentPlayer: '1',
244252
currentPlayerMoves: 0,
245253
numPlayers: 2,
246254
phase: 'default',
247255
playOrder: ['0', '1'],
248256
playOrderPos: 1,
257+
stats: {
258+
phase: { allPlayed: false, numMoves: {} },
259+
turn: { allPlayed: false, numMoves: {} },
260+
},
249261
turn: 1,
250262
},
251-
log: [ActionCreators.gameEvent('endTurn')],
263+
log: [
264+
{
265+
payload: {
266+
args: undefined,
267+
credentials: undefined,
268+
playerID: undefined,
269+
type: 'endTurn',
270+
},
271+
type: 'GAME_EVENT',
272+
},
273+
],
252274
});
253275
io.socket.emit.mockReset();
254276

0 commit comments

Comments
 (0)