Add TicTacToe client to headless tic-tac-toe
Summary: TicTacToe client implements basic operation to play Tic Tac Toe Reviewed By: passy Differential Revision: D36548545 fbshipit-source-id: cfca5dad4c42efc8272ee1ce7544914451059f14
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9bd66e6188
commit
0fcfdef465
176
desktop/examples/headless-tic-tac-toe/ticTacToeClient.js
Normal file
176
desktop/examples/headless-tic-tac-toe/ticTacToeClient.js
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
const {FlipperServerClient} = require('./flipperClient');
|
||||
const inquirer = require('inquirer');
|
||||
const {player, ticTacToePluginId} = require('./consts');
|
||||
|
||||
// Built based on https://codeburst.io/building-a-node-js-interactive-cli-3cb80ed76c86
|
||||
class TicTacToeClient {
|
||||
flipperServerClient = new FlipperServerClient();
|
||||
|
||||
async init() {
|
||||
console.log('Connecting to Flipper Server...');
|
||||
await this.flipperServerClient.init();
|
||||
console.log('Connected to Flipper Server');
|
||||
}
|
||||
|
||||
printBoard(cells) {
|
||||
console.log('| | 0 | 1 | 2 |');
|
||||
console.log(`| a | ${cells[0]} | ${cells[1]} | ${cells[2]} |`);
|
||||
console.log(`| b | ${cells[3]} | ${cells[4]} | ${cells[5]} |`);
|
||||
console.log(`| c | ${cells[6]} | ${cells[7]} | ${cells[8]} |`);
|
||||
}
|
||||
|
||||
async onStateUpdate(clientId, {winner, turn, cells}) {
|
||||
try {
|
||||
if (winner !== ' ') {
|
||||
const {next} = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'next',
|
||||
message: `Game finished! ${
|
||||
winner === player
|
||||
? 'You won!!! 🥳🎉🎇'
|
||||
: 'Not this time, rookie. Try harder.'
|
||||
}`,
|
||||
choices: ['Try again', 'Exit game'],
|
||||
default: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
if (next === 'Exit game') {
|
||||
process.exit(0);
|
||||
return;
|
||||
}
|
||||
await this.reset(clientId);
|
||||
return;
|
||||
}
|
||||
|
||||
this.printBoard(cells);
|
||||
|
||||
if (turn === player) {
|
||||
const {move} = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'move',
|
||||
message: 'Your turn...',
|
||||
choices: cells
|
||||
.map((value, i) => {
|
||||
// 97 - "a" in ASCII, 98 - "b", 99 - "c"
|
||||
const code0 = 97 + Math.floor(i / 3);
|
||||
const code1 = i % 3;
|
||||
const encoded = `${String.fromCharCode(code0)}${code1}`;
|
||||
|
||||
return value === ' ' ? {name: encoded, value: i} : null;
|
||||
})
|
||||
.filter((val) => !!val),
|
||||
default: 0,
|
||||
},
|
||||
]);
|
||||
this.move(clientId, move);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Waiting for the mobile player...');
|
||||
} catch (e) {
|
||||
console.error('TicTacToeClient.onStateUpdate -> error', e);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async startGame(clientId) {
|
||||
console.log('Starting game...');
|
||||
const state = await this.flipperServerClient.exec(
|
||||
'companion-plugin-subscribe',
|
||||
[clientId, ticTacToePluginId, 'state'],
|
||||
);
|
||||
console.log('Game on!');
|
||||
|
||||
this.onStateUpdate(clientId, state);
|
||||
|
||||
this.flipperServerClient.on(
|
||||
'companion-plugin-state-update',
|
||||
async ({data}) => this.onStateUpdate(clientId, data),
|
||||
);
|
||||
}
|
||||
|
||||
async move(clientId, cell) {
|
||||
console.log('Sending your move...');
|
||||
await this.flipperServerClient.exec('companion-plugin-exec', [
|
||||
clientId,
|
||||
ticTacToePluginId,
|
||||
'makeMove',
|
||||
[player, cell],
|
||||
]);
|
||||
console.log('Sent your move');
|
||||
}
|
||||
|
||||
async reset(clientId) {
|
||||
console.log('Restarting...');
|
||||
await this.flipperServerClient.exec('companion-plugin-exec', [
|
||||
clientId,
|
||||
ticTacToePluginId,
|
||||
'reset',
|
||||
]);
|
||||
}
|
||||
|
||||
async startTicTacToePlugin(clientId) {
|
||||
console.log('Querying available plugins...');
|
||||
const availablePlugins = await this.flipperServerClient.exec(
|
||||
'companion-plugin-list',
|
||||
[clientId],
|
||||
);
|
||||
console.log('Available plugins:', JSON.stringify(availablePlugins));
|
||||
|
||||
if (
|
||||
!availablePlugins.some(({pluginId}) => pluginId === ticTacToePluginId)
|
||||
) {
|
||||
throw new Error('Tic-Tac-Toe plugin is not supported by the app');
|
||||
}
|
||||
|
||||
console.log('Starting Tic-Tac-Toe plugin...');
|
||||
|
||||
await this.flipperServerClient.exec('companion-plugin-start', [
|
||||
clientId,
|
||||
ticTacToePluginId,
|
||||
]);
|
||||
|
||||
console.log('Started Tic-Tac-Toe plugin');
|
||||
}
|
||||
|
||||
async selectClient() {
|
||||
console.log('Querying connected clients...');
|
||||
const clients = await this.flipperServerClient.exec('client-list', []);
|
||||
console.log('Found clients: ', JSON.stringify(clients));
|
||||
|
||||
if (!clients.length) {
|
||||
throw new Error(
|
||||
'No clinets connected. Please, start your app and try again.',
|
||||
);
|
||||
}
|
||||
|
||||
const {clientId} = await inquirer.prompt([
|
||||
{
|
||||
type: 'list',
|
||||
name: 'clientId',
|
||||
message: 'Choose your client (application)',
|
||||
choices: clients.map(({id, query}) => ({
|
||||
name: `${query.app} (${query.os}) on ${query.device}`,
|
||||
value: id,
|
||||
})),
|
||||
default: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
return clientId;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {TicTacToeClient};
|
||||
Reference in New Issue
Block a user