Skip to content

Commit f8b551b

Browse files
authored
Merge pull request #18 from barlock/get-whole-board
Optimize UI with a single call to get the whole board
2 parents f49a013 + 04d4ab7 commit f8b551b

File tree

5 files changed

+97
-110
lines changed

5 files changed

+97
-110
lines changed

packages/stratego-four/contracts/Stratego4.sol

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ pragma solidity ^0.5.0;
33
contract Stratego4 {
44
enum GameState { Joining, AddingPieces, InProgress, Finished }
55

6+
event PieceMoved (
7+
bytes32 rankHash
8+
);
9+
610
struct Piece {
711
uint8 x;
812
uint8 y;
@@ -65,12 +69,6 @@ contract Stratego4 {
6569
return game.playerAddresses;
6670
}
6771

68-
function playerPieces(address playerAddress) public view returns(bytes32[] memory) {
69-
Game storage game = _currentGame(playerAddress);
70-
71-
return game.players[playerAddress].pieceRankHashes;
72-
}
73-
7472
function isPlayersTurn(address playerAddress) public view returns(bool) {
7573
Game storage game = _currentGame(playerAddress);
7674

@@ -98,6 +96,8 @@ contract Stratego4 {
9896
game.pieceLocations[x][y] = rankHash;
9997
piece.x = x;
10098
piece.y = y;
99+
100+
emit PieceMoved(rankHash);
101101
}
102102

103103
function addPiece(address playerAddress, uint8 x, uint8 y, bytes32 rankHash, bool isFlagCarrier) public {
@@ -141,4 +141,36 @@ contract Stratego4 {
141141

142142
return (piece.x, piece.y, piece.isFlagCarrier, piece.rank, rankHash);
143143
}
144+
145+
function getGamePieces(address playerAddress) public view
146+
returns(uint8[80] memory, uint8[80] memory, bool[80] memory, uint8[80] memory, bytes32[80] memory, address[80] memory)
147+
{
148+
uint8[80] memory xs;
149+
uint8[80] memory ys;
150+
bool[80] memory isFlagCarriers;
151+
uint8[80] memory ranks;
152+
bytes32[80] memory rankHashes;
153+
address[80] memory players;
154+
Game storage game = _currentGame(playerAddress);
155+
156+
for (uint i = 0; i < game.playerAddresses.length; i += 1) {
157+
address playerIAddress = game.playerAddresses[i];
158+
Player storage player = game.players[playerIAddress];
159+
160+
for (uint j = 0; j < player.pieceRankHashes.length; j += 1) {
161+
bytes32 rankHash = player.pieceRankHashes[j];
162+
Piece storage piece = player.pieces[rankHash];
163+
uint returnIndex = i * 20 + j;
164+
165+
xs[returnIndex] = piece.x;
166+
ys[returnIndex] = piece.y;
167+
isFlagCarriers[returnIndex] = piece.isFlagCarrier;
168+
ranks[returnIndex] = piece.rank;
169+
rankHashes[returnIndex] = rankHash;
170+
players[returnIndex] = playerIAddress;
171+
}
172+
}
173+
174+
return (xs, ys, isFlagCarriers, ranks, rankHashes, players);
175+
}
144176
}

packages/stratego-four/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ services:
3131
image: trufflesuite/ganache-cli
3232
ports:
3333
- 8545:8545
34-
- 8546:8546
34+
- 8546:8545
3535
command:
3636
- --gasPrice=0
3737

packages/stratego-four/src/game/gameSaga.js

Lines changed: 15 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import {
1010
selectAccounts,
1111
selectPlayerColor,
1212
selectPlayer,
13-
selectCurrentPlayerColors,
14-
selectGameCache
13+
selectPieces
1514
} from './gameSelectors';
1615
import defaultPieceSetup from './defaultPieceSetup';
1716

@@ -61,6 +60,13 @@ function* initializePlayer({ player }) {
6160
stratego4.methods.isPlayersTurn.cacheCall(player, { ...ops })
6261
)
6362
);
63+
64+
yield put(
65+
setCacheKey(
66+
'getGamePieces',
67+
stratego4.methods.getGamePieces.cacheCall(player, { ...ops })
68+
)
69+
);
6470
}
6571

6672
/**
@@ -105,81 +111,29 @@ export function* initializePlayerPieces() {
105111
);
106112
});
107113
}
108-
109-
/**
110-
* Update the piece cache for a player
111-
*
112-
* @param {Array<string>} pieces - Array of piece rank hashes
113-
* @param {string} playerAddress - Address of player to update
114-
*/
115-
export function* updatePieceCache(pieces, playerAddress) {
116-
const ops = yield defaultTxOps();
117-
const playerColors = yield select(selectCurrentPlayerColors);
118-
const gameCache = yield select(selectGameCache);
119-
const player = playerColors.find(player => player.address === playerAddress);
120-
121-
if (!player) {
122-
// Skip if a player isn't found. Happens when changing to a new game
123-
return;
124-
}
125-
126-
const gameCacheKey = `getPiece-${player.color}`;
127-
const currentPieceCache = gameCache[gameCacheKey] || [];
128-
129-
yield put(
130-
setCacheKey(
131-
gameCacheKey,
132-
pieces.map(piece => {
133-
const args = [playerAddress, piece, { ...ops }];
134-
const cacheKey = stratego4.generateArgsHash(args);
135-
136-
if (!currentPieceCache.includes(cacheKey)) {
137-
stratego4.methods.getPiece.cacheCall(...args);
138-
}
139-
140-
return cacheKey;
141-
})
142-
)
143-
);
144-
}
145-
146114
/**
147115
* Handle when drizzle receives player piece rank hashes
148116
*
149117
* @param {Object} action - redux action
150118
*/
151-
export function* handleGotPlayerPieces(action) {
119+
export function* handleGotGamePieces(action) {
152120
const player = yield select(selectPlayer);
153121
const actionPlayer = action.args[0];
154122
const playerColor = yield select(selectPlayerColor);
155-
const pieces = action.value;
156-
const isAlreadySetup = pieces.length > 0;
123+
const gamePieces = yield select(selectPieces);
157124

158125
const isCurrentPlayer = actionPlayer === player;
159126

160127
if (!playerColor) {
161128
return;
162129
}
163130

131+
const pieces = gamePieces[playerColor];
132+
const isAlreadySetup = pieces.length > 0;
133+
164134
if (isCurrentPlayer && !isAlreadySetup) {
165135
yield initializePlayerPieces();
166136
}
167-
168-
yield updatePieceCache(pieces, actionPlayer);
169-
}
170-
171-
/**
172-
* Handle when drizzle receives current player addresses
173-
*
174-
* @param {Object} action - Redux action
175-
*/
176-
export function* handleGotCurrentPlayers(action) {
177-
const ops = yield defaultTxOps();
178-
const currentPlayers = action.value;
179-
180-
currentPlayers.forEach(player =>
181-
stratego4.methods.playerPieces.cacheCall(player, { ...ops })
182-
);
183137
}
184138

185139
/**
@@ -189,19 +143,14 @@ export function* handleGotCurrentPlayers(action) {
189143
*/
190144
export function* handleGotContractVar(action) {
191145
switch (action.variable) {
192-
case 'playerPieces':
193-
yield handleGotPlayerPieces(action);
194-
break;
195-
196-
case 'currentPlayers':
197-
yield handleGotCurrentPlayers(action);
146+
case 'getGamePieces':
147+
yield handleGotGamePieces(action);
198148
break;
199149

200150
default:
201151
break;
202152
}
203153
}
204-
205154
/**
206155
* A player has joined the a game
207156
*

packages/stratego-four/src/game/gameSelectors.js

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,40 +56,10 @@ const selectCacheValue = key =>
5656
}
5757
);
5858

59-
/**
60-
* Create a selector for a player color's pieces
61-
*
62-
* @param {string} color - The player color
63-
* @returns {Function} - Cache selector
64-
*/
65-
const selectPlayerPieces = color =>
66-
createSelector(
67-
selectGameCache,
68-
selectContract,
69-
(gameCache, contract) => {
70-
const pieceCacheKeys = gameCache[`getPiece-${color}`] || [];
71-
72-
return pieceCacheKeys
73-
.map(cacheKey => contract.getPiece[cacheKey])
74-
.filter(cache => cache)
75-
.map(({ value }) => ({
76-
x: value[0],
77-
y: value[1],
78-
isFlagCarrier: value[2],
79-
rank: value[3],
80-
rankHash: value[4]
81-
}));
82-
}
83-
);
84-
8559
export const selectCurrentGameId = selectCacheValue('currentGame');
8660
export const selectCurrentPlayers = selectCacheValue('currentPlayers');
8761
export const selectIsPlayersTurn = selectCacheValue('isPlayersTurn');
88-
89-
export const selectRedPlayerPieces = selectPlayerPieces('red');
90-
export const selectGreenPlayerPieces = selectPlayerPieces('green');
91-
export const selectBluePlayerPieces = selectPlayerPieces('blue');
92-
export const selectYellowPlayerPieces = selectPlayerPieces('yellow');
62+
export const selectGamePieces = selectCacheValue('getGamePieces');
9363

9464
const playerColors = new Map([
9565
[-1, ''],
@@ -117,10 +87,46 @@ export const selectPlayerColor = createSelector(
11787
(players.find(player => player.address === playerAddress) || {}).color
11888
);
11989

90+
/**
91+
* Create an initial empty board state
92+
*
93+
* @returns {Object} An Empty board
94+
*/
95+
const initialBoard = () => ({
96+
red: [],
97+
green: [],
98+
blue: [],
99+
yellow: []
100+
});
101+
120102
export const selectPieces = createSelector(
121-
selectRedPlayerPieces,
122-
selectGreenPlayerPieces,
123-
selectBluePlayerPieces,
124-
selectYellowPlayerPieces,
125-
(red, green, blue, yellow) => ({ red, green, blue, yellow })
103+
selectGamePieces,
104+
selectCurrentPlayerColors,
105+
(gamePieces, playerColors) => {
106+
if (!gamePieces) {
107+
return initialBoard();
108+
}
109+
110+
return gamePieces[0]
111+
.map((x, index) => ({
112+
x: gamePieces[0][index],
113+
y: gamePieces[1][index],
114+
isFlagCarrier: gamePieces[2][index],
115+
rank: gamePieces[3][index],
116+
rankHash: gamePieces[4][index],
117+
player: gamePieces[5][index]
118+
}))
119+
.filter(piece => piece.x !== '0')
120+
.reduce((board, piece) => {
121+
const color = (
122+
playerColors.find(player => player.address === piece.player) || {}
123+
).color;
124+
125+
if (color) {
126+
board[color].push(piece);
127+
}
128+
129+
return board;
130+
}, initialBoard());
131+
}
126132
);

packages/stratego-four/src/store/drizzleOptions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const mnemonic =
44

55
export default {
66
contracts: [require('../build/contracts/Stratego4')],
7-
7+
events: ['PieceMoved'],
88
web3: {
99
web3: {
1010
customProvider: pantheonProvider(mnemonic)

0 commit comments

Comments
 (0)