Skip to content

Commit

Permalink
write turn / phase stats in ctx.stats
Browse files Browse the repository at this point in the history
currently contains numMoves, an object that tracks the number of moves made by each player in the current turn / phase.
  • Loading branch information
darthfiddler committed Jul 31, 2018
1 parent 84f07c6 commit 43dcaac
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 44 deletions.
64 changes: 46 additions & 18 deletions src/core/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,9 @@ export function FlowWithPhases({

const shouldEndTurn = ({ G, ctx }) => {
const conf = phaseMap[ctx.phase];
if (conf.movesPerTurn && ctx.currentPlayerMoves >= conf.movesPerTurn) {

const currentPlayerMoves = ctx.stats.turn.numMoves[ctx.currentPlayer] || 0;
if (conf.movesPerTurn && currentPlayerMoves >= conf.movesPerTurn) {
return true;
}
return conf.endTurnIf(G, ctx);
Expand All @@ -345,8 +347,19 @@ export function FlowWithPhases({
const startPhase = function(state, config) {
const G = config.onPhaseBegin(state.G, state.ctx);
const ctx = InitTurnOrderState(state.G, state.ctx, config.turnOrder);

// Reset stats.
ctx.stats = {
...ctx.stats,
phase: {
...ctx.stats.phase,
numMoves: {},
allPlayed: false,
},
};

const allowedMoves = config.allowedMoves(G, ctx);
return { ...state, G, ctx: { ...ctx, allowedMoves, _played: [] } };
return { ...state, G, ctx: { ...ctx, allowedMoves } };
};

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

// Reset stats.
ctx.stats = {
...ctx.stats,
turn: {
...ctx.stats.turn,
numMoves: {},
allPlayed: false,
},
};

return { ...state, G, ctx, _undo, _redo: [] };
};

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

// Prevent ending the turn if movesPerTurn haven't been made.
if (conf.movesPerTurn && ctx.currentPlayerMoves < conf.movesPerTurn) {
const currentPlayerMoves = ctx.stats.turn.numMoves[ctx.currentPlayer] || 0;
if (conf.movesPerTurn && currentPlayerMoves < conf.movesPerTurn) {
return state;
}

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

// Update state.
ctx = {
...ctx,
turn,
currentPlayerMoves: 0,
};
ctx = { ...ctx, turn };

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

function updateStats(state, key, playerID) {
const moves = (state.ctx.stats[key].numMoves[playerID] || 0) + 1;
const numMoves = { ...state.ctx.stats[key].numMoves, [playerID]: moves };
const t = { ...state.ctx.stats[key], numMoves };

if (Object.keys(numMoves).length == state.ctx.numPlayers) {
t.allPlayed = true;
}

const stats = { ...state.ctx.stats, [key]: t };
const ctx = { ...state.ctx, stats };

return { ...state, ctx };
}

function processMove(state, action, dispatch) {
let conf = phaseMap[state.ctx.phase];

const currentPlayerMoves = state.ctx.currentPlayerMoves + 1;
let _played = state.ctx._played;
if (!_played.includes(action.playerID)) {
_played = [..._played, action.playerID];
}
const allPlayed = _played.length == state.ctx.numPlayers;
state = updateStats(state, 'turn', action.playerID);
state = updateStats(state, 'phase', action.playerID);

// Update actionPlayers if _actionPlayersOnce is set.
let actionPlayers = state.ctx.actionPlayers;
Expand All @@ -529,9 +560,6 @@ export function FlowWithPhases({
ctx: {
...state.ctx,
actionPlayers,
currentPlayerMoves,
_played,
allPlayed,
},
};

Expand Down Expand Up @@ -625,7 +653,7 @@ export function FlowWithPhases({
currentPlayerMoves: 0,
playOrder: Array.from(Array(numPlayers), (d, i) => i + ''),
playOrderPos: 0,
_played: [],
stats: { turn: { numMoves: {} }, phase: { numMoves: {} } },
allPlayed: false,
phase: phases[0].name,
}),
Expand Down
18 changes: 8 additions & 10 deletions src/core/flow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ test('movesPerTurn', () => {
let flow = FlowWithPhases({ movesPerTurn: 2 });
let state = { ctx: flow.ctx(2) };
expect(state.ctx.turn).toBe(0);
state = flow.processMove(state, makeMove().payload);
state = flow.processMove(state, makeMove('move', null, '0').payload);
expect(state.ctx.turn).toBe(0);
state = flow.processGameEvent(state, gameEvent('endTurn'));
expect(state.ctx.turn).toBe(0);
state = flow.processMove(state, makeMove().payload);
state = flow.processMove(state, makeMove('move', null, '0').payload);
expect(state.ctx.turn).toBe(1);
}

Expand All @@ -71,17 +71,17 @@ test('movesPerTurn', () => {
});
let state = { ctx: flow.ctx(2) };
expect(state.ctx.turn).toBe(0);
state = flow.processMove(state, makeMove().payload);
state = flow.processMove(state, makeMove('move', null, '0').payload);
expect(state.ctx.turn).toBe(0);
state = flow.processGameEvent(state, gameEvent('endTurn'));
expect(state.ctx.turn).toBe(0);
state = flow.processMove(state, makeMove().payload);
state = flow.processMove(state, makeMove('move', null, '0').payload);
expect(state.ctx.turn).toBe(1);

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

expect(state.ctx.turn).toBe(1);
state = flow.processMove(state, makeMove().payload);
state = flow.processMove(state, makeMove('move', null, '1').payload);
expect(state.ctx.turn).toBe(2);
}
});
Expand Down Expand Up @@ -756,7 +756,7 @@ test('endTurn is not called twice in one move', () => {
expect(state.ctx.turn).toBe(2);
});

test('played / allPlayed', () => {
test('allPlayed', () => {
let game = Game({
moves: { A: () => ({ A: true }) },
});
Expand All @@ -767,10 +767,8 @@ test('played / allPlayed', () => {

state = reducer(state, makeMove('A', null, '0'));
state = reducer(state, gameEvent('endTurn', null, '0'));
expect(state.ctx.allPlayed).toBe(false);
expect(state.ctx._played).toEqual(['0']);
expect(state.ctx.stats.phase.allPlayed).toBe(false);
state = reducer(state, makeMove('A', null, '1'));
state = reducer(state, gameEvent('endTurn', null, '1'));
expect(state.ctx.allPlayed).toBe(true);
expect(state.ctx._played).toEqual(['0', '1']);
expect(state.ctx.stats.phase.allPlayed).toBe(true);
});
54 changes: 38 additions & 16 deletions src/server/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,33 +183,39 @@ test('action', async () => {
G: {},
ctx: {
_random: { seed: 0 },
actionPlayers: ['0'],
allPlayed: false,
allowedMoves: null,
currentPlayer: '0',
actionPlayers: ['0'],
currentPlayerMoves: 0,
allPlayed: false,
_played: [],
numPlayers: 2,
phase: 'default',
turn: 0,
playOrder: ['0', '1'],
playOrderPos: 0,
stats: {
phase: { allPlayed: false, numMoves: {} },
turn: { numMoves: {} },
},
turn: 0,
},
},
],
ctx: {
_random: { seed: 0 },
actionPlayers: ['0'],
allPlayed: false,
allowedMoves: null,
currentPlayer: '0',
actionPlayers: ['0'],
currentPlayerMoves: 0,
allPlayed: false,
_played: [],
numPlayers: 2,
phase: 'default',
turn: 0,
playOrder: ['0', '1'],
playOrderPos: 0,
stats: {
phase: { allPlayed: false, numMoves: {} },
turn: { allPlayed: false, numMoves: {} },
},
turn: 0,
},
log: [],
},
Expand All @@ -220,35 +226,51 @@ test('action', async () => {
G: {},
ctx: {
_random: { seed: 0 },
actionPlayers: ['1'],
allPlayed: false,
allowedMoves: null,
currentPlayer: '1',
actionPlayers: ['1'],
currentPlayerMoves: 0,
allPlayed: false,
_played: [],
numPlayers: 2,
phase: 'default',
turn: 1,
playOrder: ['0', '1'],
playOrderPos: 1,
stats: {
phase: { allPlayed: false, numMoves: {} },
turn: { allPlayed: false, numMoves: {} },
},
turn: 1,
},
},
],
ctx: {
_random: undefined,
allowedMoves: null,
currentPlayer: '1',
actionPlayers: ['1'],
allPlayed: false,
_played: [],
allowedMoves: null,
currentPlayer: '1',
currentPlayerMoves: 0,
numPlayers: 2,
phase: 'default',
playOrder: ['0', '1'],
playOrderPos: 1,
stats: {
phase: { allPlayed: false, numMoves: {} },
turn: { allPlayed: false, numMoves: {} },
},
turn: 1,
},
log: [ActionCreators.gameEvent('endTurn')],
log: [
{
payload: {
args: undefined,
credentials: undefined,
playerID: undefined,
type: 'endTurn',
},
type: 'GAME_EVENT',
},
],
});
io.socket.emit.mockReset();

Expand Down

0 comments on commit 43dcaac

Please sign in to comment.