github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/sdk/examples/xo_javascript/xo_handler.js (about) 1 /** 2 * Copyright 2017-2018 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * ------------------------------------------------------------------------------ 16 */ 17 18 'use strict' 19 20 const XoPayload = require('./xo_payload') 21 22 const { XO_NAMESPACE, XO_FAMILY, XoState } = require('./xo_state') 23 24 const { TransactionHandler } = require('sawtooth-sdk/processor/handler') 25 const { InvalidTransaction } = require('sawtooth-sdk/processor/exceptions') 26 27 const _gameToStr = (board, state, player1, player2, name) => { 28 board = board.replace(/-/g, ' ') 29 board = board.split('') 30 let out = '' 31 out += `GAME: ${name}\n` 32 out += `PLAYER 1: ${player1.substring(0, 6)}\n` 33 out += `PLAYER 2: ${player2.substring(0, 6)}\n` 34 out += `STATE: ${state}\n` 35 out += `\n` 36 out += `${board[0]} | ${board[1]} | ${board[2]} \n` 37 out += `---|---|--- \n` 38 out += `${board[3]} | ${board[4]} | ${board[5]} \n` 39 out += `---|---|--- \n` 40 out += `${board[6]} | ${board[7]} | ${board[8]} \n` 41 return out 42 } 43 44 const _display = msg => { 45 let n = msg.search('\n') 46 let length = 0 47 48 if (n !== -1) { 49 msg = msg.split('\n') 50 for (let i = 0; i < msg.length; i++) { 51 if (msg[i].length > length) { 52 length = msg[i].length 53 } 54 } 55 } else { 56 length = msg.length 57 msg = [msg] 58 } 59 60 console.log('+' + '-'.repeat(length + 2) + '+') 61 for (let i = 0; i < msg.length; i++) { 62 let len = length - msg[i].length 63 64 if (len % 2 === 1) { 65 console.log( 66 '+ ' + 67 ' '.repeat(Math.floor(len / 2)) + 68 msg[i] + 69 ' '.repeat(Math.floor(len / 2 + 1)) + 70 ' +' 71 ) 72 } else { 73 console.log( 74 '+ ' + 75 ' '.repeat(Math.floor(len / 2)) + 76 msg[i] + 77 ' '.repeat(Math.floor(len / 2)) + 78 ' +' 79 ) 80 } 81 } 82 console.log('+' + '-'.repeat(length + 2) + '+') 83 } 84 85 const _isWin = (board, letter) => { 86 let wins = [ 87 [1, 2, 3], 88 [4, 5, 6], 89 [7, 8, 9], 90 [1, 4, 7], 91 [2, 5, 8], 92 [3, 6, 9], 93 [1, 5, 9], 94 [3, 5, 7] 95 ] 96 let win 97 for (let i = 0; i < wins.length; i++) { 98 win = wins[i] 99 if (board[win[0] - 1] === letter && 100 board[win[1] - 1] === letter && 101 board[win[2] - 1] === letter) { 102 return true 103 } 104 } 105 return false 106 } 107 108 class XOHandler extends TransactionHandler { 109 constructor () { 110 super(XO_FAMILY, ['1.0'], [XO_NAMESPACE]) 111 } 112 113 apply (transactionProcessRequest, context) { 114 let payload = XoPayload.fromBytes(transactionProcessRequest.payload) 115 let xoState = new XoState(context) 116 let header = transactionProcessRequest.header 117 let player = header.signerPublicKey 118 119 if (payload.action === 'create') { 120 return xoState.getGame(payload.name) 121 .then((game) => { 122 if (game !== undefined) { 123 throw new InvalidTransaction('Invalid Action: Game already exists.') 124 } 125 126 let createdGame = { 127 name: payload.name, 128 board: '---------', 129 state: 'P1-NEXT', 130 player1: '', 131 player2: '' 132 } 133 134 _display(`Player ${player.toString().substring(0, 6)} created game ${payload.name}`) 135 136 return xoState.setGame(payload.name, createdGame) 137 }) 138 } else if (payload.action === 'take') { 139 return xoState.getGame(payload.name) 140 .then((game) => { 141 try { 142 parseInt(payload.space) 143 } catch (err) { 144 throw new InvalidTransaction('Space could not be converted as an integer.') 145 } 146 147 if (payload.space < 1 || payload.space > 9) { 148 throw new InvalidTransaction('Invalid space ' + payload.space) 149 } 150 151 if (game === undefined) { 152 throw new InvalidTransaction( 153 'Invalid Action: Take requires an existing game.' 154 ) 155 } 156 if (['P1-WIN', 'P2-WIN', 'TIE'].includes(game.state)) { 157 throw new InvalidTransaction('Invalid Action: Game has ended.') 158 } 159 160 if (game.player1 === '') { 161 game.player1 = player 162 } else if (game.player2 === '') { 163 game.player2 = player 164 } 165 let boardList = game.board.split('') 166 167 if (boardList[payload.space - 1] !== '-') { 168 throw new InvalidTransaction('Invalid Action: Space already taken.') 169 } 170 171 if (game.state === 'P1-NEXT' && player === game.player1) { 172 boardList[payload.space - 1] = 'X' 173 game.state = 'P2-NEXT' 174 } else if ( 175 game.state === 'P2-NEXT' && 176 player === game.player2 177 ) { 178 boardList[payload.space - 1] = 'O' 179 game.state = 'P1-NEXT' 180 } else { 181 throw new InvalidTransaction( 182 `Not this player's turn: ${player.toString().substring(0, 6)}` 183 ) 184 } 185 186 game.board = boardList.join('') 187 188 if (_isWin(game.board, 'X')) { 189 game.state = 'P1-WIN' 190 } else if (_isWin(game.board, 'O')) { 191 game.state = 'P2-WIN' 192 } else if (game.board.search('-') === -1) { 193 game.state = 'TIE' 194 } 195 196 let playerString = player.toString().substring(0, 6) 197 198 _display( 199 `Player ${playerString} takes space: ${payload.space}\n\n` + 200 _gameToStr( 201 game.board, 202 game.state, 203 game.player1, 204 game.player2, 205 payload.name 206 ) 207 ) 208 209 return xoState.setGame(payload.name, game) 210 }) 211 } else if (payload.action === 'delete') { 212 return xoState.getGame(payload.name) 213 .then((game) => { 214 if (game === undefined) { 215 throw new InvalidTransaction( 216 `No game exists with name ${payload.name}: unable to delete`) 217 } 218 return xoState.deleteGame(payload.name) 219 }) 220 } else { 221 throw new InvalidTransaction( 222 `Action must be create, delete, or take not ${payload.action}` 223 ) 224 } 225 } 226 } 227 228 module.exports = XOHandler