commands/play.js
/**
         * @brief This function is invoked when the database lookup
         *        operation to find the channel's ongoing game is complete.
         *        If a valid game is found, and the current user is allowed to
         *        make a move, then the game board is updated. After every move,
         *        the function checks if this move caused the current player to
         *        win or if the game ended in a tie. The game is updated in the
         *        database accordingly.
         *
         * @param error db lookup error
         * @param game valid game from the db
         *
         * @return none
         */
@brief This function is invoked when the database lookup
operation to find the channel's ongoing game is complete.
If a valid game is found, and the current user is allowed to
make a move, then the game board is updated. After every move,
the function checks if this move caused the current player to
win or if the game ended in a tie. The game is updated in the
database accordingly.

@param error db lookup error
@param game valid game from the db

@return none
@brief This function is invoked when the database lookup operation to find the channel ' s ongoing game is complete . If a valid game is found and the current user is allowed to make a move then the game board is updated . After every move the function checks if this move caused the current player to win or if the game ended in a tie . The game is updated in the database accordingly . @param error db lookup error @param game valid game from the db @return none
function dbLookupCallback(error, game) {
            if (error !== undefined && error !== null) {
                logger.error(error);
                return res.json(
                    slackUtil.createResponse({
                        text: labels.DB_ERROR,
                        response_type: "ephemeral"
                    })
                );
            }
            if (game === undefined || game === null) {
                return res.json(
                    slackUtil.createResponse({
                        text: labels.GAME_NOT_FOUND_ERROR,
                        response_type: "ephemeral"
                    })
                );
            }
            let currentPlayer = game.currentPlayer;
            let players = game.players;
            if (players[0].name !== player && players[1].name !== player) {
                return res.json(
                    slackUtil.createResponse({
                        text: labels.USER_ERROR,
                        response_type: "ephemeral",
                        attachments: [{
                            text: util.format(
                                labels.USER_DETAIL_ERROR,
                                slackUtil.getUserDisplay(players[0]),
                                slackUtil.getUserDisplay(players[1])
                            ),
                            color: "#ff0000",
                            mrkdwn_in: [
                                "text"
                            ]
                        }]
                    })
                );
            }
            let index = 0;
            if (players[1].name === currentPlayer) {
                index = 1;
            }
            if (currentPlayer !== player) {
                return res.json(
                    slackUtil.createResponse({
                        text: labels.USER_ERROR,
                        response_type: "ephemeral",
                        attachments: [{
                            text: util.format(
                                labels.TURN_ERROR,
                                slackUtil.getUserDisplay(players[index])
                            ),
                            color: "#ff0000",
                            mrkdwn_in: [
                                "text"
                            ]
                        }]
                    })
                );
            }
            if (move >= game.board.length
                    || game.board[move] !== 0) {
                return res.json(
                    slackUtil.createResponse({
                        text: labels.CMD_ERROR,
                        response_type: "ephemeral",
                        attachments: [{
                            text: labels.CMD_DETAIL_ERROR,
                            color: "#ff0000",
                            mrkdwn_in: [
                                "text"
                            ]
                        }]
                    })
                );
            }
            let winner;
            game.board[move] = getMoveState(index);
            game.history.push({
                player: currentPlayer,
                move
            });
            game.markModified("board");
            game.markModified("history");
            let winStatus = hasWon(game.board, move);
            if (winStatus.status === true) {
                game.state = constants.gameState.WIN;
                game.winner = currentPlayer;
                winner = players[index];
            } else if (game.board.indexOf(constants.moveState.EMPTY) === -1) {
                game.state = constants.gameState.TIE;
            } else {
                game.currentPlayer = players[(index + 1) % 2].name;
            }
            db.update(game, function (error) {
                if (error) {
                    logger.error(error);
                    return res.send(error);
                }
                if (winner !== undefined) {
                    return res.json(
                        slackUtil.createResponse({
                            text: util.format(
                                labels.WIN_TEXT,
                                slackUtil.getUserDisplay(winner)
                            ),
                            attachments: [{
                                text: drawer.draw(game.board, winStatus),
                                color: "#36a64f",
                                mrkdwn_in: [
                                    "text"
                                ]
                            }]
                        })
                    );
                }
                if (game.state === constants.gameState.TIE) {
                    return res.json(
                        slackUtil.createResponse({
                            text: labels.TIE_TEXT,
                            attachments: [{
                                text: drawer.draw(game.board, winStatus),
                                color: "#36a64f",
                                mrkdwn_in: [
                                    "text"
                                ]
                            }]
                        })
                    );
                }
                res.json(
                    slackUtil.createResponse({
                        text: util.format(
                            labels.NEXT_TURN_TEXT,
                            slackUtil.getUserDisplay(players[index]),
                            slackUtil.getUserDisplay(players[(index + 1) % 2])
                        ),
                        attachments: [{
                            text: drawer.draw(game.board),
                            color: "#36a64f",
                            mrkdwn_in: [
                                "text"
                            ]
                        }]
                    })
                );
            });
        }
function dbLookupCallback ( error , game ) { if ( error !== undefined && error !== null ) { logger . error ( error ) ; return res . json ( slackUtil . createResponse ( { text : labels . DB_ERROR , response_type : "ephemeral" } ) ) ; } if ( game === undefined || game === null ) { return res . json ( slackUtil . createResponse ( { text : labels . GAME_NOT_FOUND_ERROR , response_type : "ephemeral" } ) ) ; } let currentPlayer = game . currentPlayer ; let players = game . players ; if ( players [ 0 ] . name !== player && players [ 1 ] . name !== player ) { return res . json ( slackUtil . createResponse ( { text : labels . USER_ERROR , response_type : "ephemeral" , attachments : [ { text : util . format ( labels . USER_DETAIL_ERROR , slackUtil . getUserDisplay ( players [ 0 ] ) , slackUtil . getUserDisplay ( players [ 1 ] ) ) , color : "#ff0000" , mrkdwn_in : [ "text" ] } ] } ) ) ; } let index = 0 ; if ( players [ 1 ] . name === currentPlayer ) { index = 1 ; } if ( currentPlayer !== player ) { return res . json ( slackUtil . createResponse ( { text : labels . USER_ERROR , response_type : "ephemeral" , attachments : [ { text : util . format ( labels . TURN_ERROR , slackUtil . getUserDisplay ( players [ index ] ) ) , color : "#ff0000" , mrkdwn_in : [ "text" ] } ] } ) ) ; } if ( move >= game . board . length || game . board [ move ] !== 0 ) { return res . json ( slackUtil . createResponse ( { text : labels . CMD_ERROR , response_type : "ephemeral" , attachments : [ { text : labels . CMD_DETAIL_ERROR , color : "#ff0000" , mrkdwn_in : [ "text" ] } ] } ) ) ; } let winner ; game . board [ move ] = getMoveState ( index ) ; game . history . push ( { player : currentPlayer , move } ) ; game . markModified ( "board" ) ; game . markModified ( "history" ) ; let winStatus = hasWon ( game . board , move ) ; if ( winStatus . status === true ) { game . state = constants . gameState . WIN ; game . winner = currentPlayer ; winner = players [ index ] ; } else if ( game . board . indexOf ( constants . moveState . EMPTY ) === - 1 ) { game . state = constants . gameState . TIE ; } else { game . currentPlayer = players [ ( index + 1 ) % 2 ] . name ; } db . update ( game , function ( error ) { if ( error ) { logger . error ( error ) ; return res . send ( error ) ; } if ( winner !== undefined ) { return res . json ( slackUtil . createResponse ( { text : util . format ( labels . WIN_TEXT , slackUtil . getUserDisplay ( winner ) ) , attachments : [ { text : drawer . draw ( game . board , winStatus ) , color : "#36a64f" , mrkdwn_in : [ "text" ] } ] } ) ) ; } if ( game . state === constants . gameState . TIE ) { return res . json ( slackUtil . createResponse ( { text : labels . TIE_TEXT , attachments : [ { text : drawer . draw ( game . board , winStatus ) , color : "#36a64f" , mrkdwn_in : [ "text" ] } ] } ) ) ; } res . json ( slackUtil . createResponse ( { text : util . format ( labels . NEXT_TURN_TEXT , slackUtil . getUserDisplay ( players [ index ] ) , slackUtil . getUserDisplay ( players [ ( index + 1 ) % 2 ] ) ) , attachments : [ { text : drawer . draw ( game . board ) , color : "#36a64f" , mrkdwn_in : [ "text" ] } ] } ) ) ; } ) ; }
@brief This function is invoked when the database lookup
        operation to find the channel's ongoing game is complete.
@brief This function is invoked when the database lookup operation to find the channel ' s ongoing game is complete .
// No ongling game found in this channel. // No ongling game found in this channel. // Check if the user running this command is the current player. // Check if the given index is available to make a move. // Make the move by marking the board. // Update the history of moves. // Check if we have a result. /* This move resulted in the current player winning. Update the
                 * game state and winner.
                 */ // The board is now full, causing a Tie. Update the game state. // No result yet. Update the currentPlayer. // Save the updated game to the database. // Check if we have a winner and return appropriate message. // Check if we have a tie and return appropriate message. // Indicate whose turn it is next and draw the current board.