Agora que você tem um item jogo na tabela, pode aprender a simular a jogada de um jogador em um jogo em andamento.
Há duas maneiras de executar essa operação. Na primeira, recupere o item usando a API GetItem. Depois atualize o item de jogo no aplicativo de acordo com a jogada realizada pelo jogador. Por fim, substitua o item existente no DynamoDB usando a API PutItem. Embora essa opção funcione, ela requer várias solicitações à tabela do DynamoDB e há riscos de sobregravar as alterações efetuadas entre a obtenção e a regravação do item de tabela.
A segunda maneira de executar essa operação é usar a chamada da API UpdateItem no DynamoDB. Com a API UpdateItem, é possível atualizar o item do DynamoDB com uma única solicitação. Especifique o item que você deseja alterar, os atributos a serem alterados e as condições a serem expressas no item. Esse é o método preferencial de efetuar uma alteração em um item porque não requer várias chamadas ao banco de dados.
No diretório scripts/, há um arquivo chamado performMove.js, que tem o seguinte conteúdo:
const AWS = require('aws-sdk')
const documentClient = new AWS.DynamoDB.DocumentClient()
const performMove = async ({ gameId, user, changedHeap, changedHeapValue }) => {
if (changedHeapValue < 0 ) {
throw new Error('Cannot set heap value below 0')
}
const params = {
TableName: 'turn-based-game',
Key: {
gameId: gameId
},
UpdateExpression: `SET lastMoveBy = :user, ${changedHeap} = :changedHeapValue`,
ConditionExpression: `(user1 = :user OR user2 = :user) AND lastMoveBy <> :user AND ${changedHeap} > :changedHeapValue`,
ExpressionAttributeValues: {
':user': user,
':changedHeapValue': changedHeapValue,
},
ReturnValues: 'ALL_NEW'
}
try {
const resp = await documentClient.update(params).promise()
console.log('Updated game: ', resp.Attributes)
} catch (error) {
console.log('Error updating item: ', error.message)
}
}
performMove({ gameId: '5b5ee7d8', user: 'theseconduser', changedHeap: 'heap1', changedHeapValue: 3 })
Esse script é um pouco complicado. Vamos segui-lo passo a passo.
Como no script anterior, importe o AWS SDK e crie uma instância do DynamoDB Document Client.
Em seguida, defina um método chamado performMove. Esse método é semelhante a um método interno que seria usado no aplicativo quando o usuário solicitasse uma jogada. O script monta os parâmetros de uma chamada da API UpdateItem. Primeiramente, ele altera dois atributos do jogo: o último usuário a fazer uma jogada e o número de elementos na pilha alterada.
Os parâmetros da API UpdateItem fazem algumas afirmativas sobre o estado atual do jogo. ConditionExpression é avaliado antes de o item ser atualizado para confirmar que o estado do item é o desejado. Você está fazendo estas três afirmativas na expressão da condição:
- O usuário que solicita realizar uma jogada é um dos dois usuários do jogo;
- A rodada atual é do usuário que está solicitando a jogada;
- O valor atual da pilha que está sendo alterada é superior ao valor para o qual está sendo alterado.
Por último, os parâmetros definem ReturnValue de ALL_NEW, o que significa que o DynamoDB retorna o item inteiro depois que seus valores são atualizados. Depois disso, o aplicativo pode avaliar o jogo para ver se há um vencedor.
Na parte inferior do arquivo, há um exemplo de como esse método é chamado no aplicativo. É possível executar o script com o seguinte comando:
A seguinte saída será exibida no terminal:
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
Você pode ver que a gravação foi bem-sucedida e que o jogo foi atualizado.
Tente executar o script no terminal novamente. A seguinte saída será exibida:
As solicitações condicionais falharam desta vez. O usuário solicitante -- theseconduser -- foi o jogador que realizou a jogada mais recente. Além disso, a pilha alterada -- heap1 -- já tinha o valor de 3, ou seja, o usuário não efetuou qualquer alteração. Por esse motivo, a solicitação foi recusada.