# Online card game with node.js and socket.io - episode 2

Source: https://tpiros.dev/blog/online-card-game-with-node-js-and-socket-io-episode-2

Here's the second post about developing an online card game (continuing from Episode 1).

I haven't had much time to spend on this over the past few weeks, but I did make progress. Remember, this tutorial doubles as a learning curve for me. I try to include my findings as I go. I'm also considering adding [CoffeeScript](http://coffeescript.org/) and [underscore.js](http://underscorejs.org/) to the project, as they have methods that could help me get where I'm going.

In this post, I'm introducing a websocket. I'll pass information between the server and the client, and I'll use the JavaScript file from the previous part.

I'll work with three files:

- `game.js` holds the logic for creating, shuffling, and dealing cards
- `server.js` is the server that serves connected clients
- `index.html` is the client

Let's define what `server.js` should do:

- Accept connections from the client
- Add users
- Remove users when they disconnect
- Deal 5 cards to each connected user

With that in mind, let's set up some variables:

```javascript
var io = require('socket.io'),
  game = require('./game');

var socket = io.listen('1.1.1.1', 1222);
socket.set('log level', 1);

var players = {};
var start = false;
var pack = game.shufflePack(game.createPack());
```

I'm also adding a helper function to get the size of an object. I'm creating the players hash/object because I want an array with my own indexes. The "problem" is that JavaScript's `length` only works on numerically indexed arrays. Quick example:

```js
var a = [];
a.push('e1', 'e2', 'e3');
console.log(a.length); //returns 3

var o = {};
o['name'] = 'Luke';
o['surname'] = 'Skywalker';
o['profession'] = 'Jedi';
console.log(o.length); //returns undefined
```

That's expected behaviour. Adding this function returns the size of the object (the number of elements):

```js
Object.size = function (obj) {
  var size = 0,
    key;
  for (key in obj) {
    if (obj.hasOwnProperty(key)) size++;
  }
  return size;
};
//test it
console.log(Object.size(o)); //returns 3
```

The final piece of `server.js` sets up the websocket and accepts connections. The flow: the user opens `index.html`, enters a username, emits a message to the server saying the player is ready, then a deal button is enabled that pulls 5 cards from the pack we created above.

```js
socket.on('connection', function (client) {
  client.on('addPlayer', function (player) {
    players[client.id] = player;
    console.log(
      'Player ' + player + 'with id: ' + client.id + 'has connected.'
    );
    console.log(Object.size(players));
    for (var key in players) {
      console.log('Players: ' + key + ': ' + players[key]);
    }
  });

  client.on('disconnect', function () {
    console.log('Player with id: ' + client.id + 'has disconnected');
    delete players[client.id];
    for (var key in players) {
      console.log('Remaining players: ' + key + ': ' + players[key]);
    }
    //reset pack
    pack = game.shufflePack(game.createPack());
  });

  client.on('dealCards', function () {
    var cards = game.draw(pack, 5, '', true);
    client.emit('showCards', cards);
    socket.sockets.emit('remainingCards', pack.length);
  });
});
```

Note the highlighted line. The difference between `client.emit()` and `socket.sockets.emit()` is significant. The latter sends the update message to all connected clients. The former sends only to the newly connected client. This lets us update the remaining card count for a player who's already connected.

The player object has the format `player["unique identifier"] = "name of player"`, which makes it easy to delete the right player on disconnect.

Let's look at `index.html`. First the HTML markup:

```html
<!DOCTYPE html>
<html>
<head>
  <script src="http://1.1.1.1:1222/socket.io/socket.io.js"><!--because I'm not using localhost, I need to add the IP address-->

    &lt;script src="jquery.js">&lt;/script>

<body>

<h1>This is the client</h1>

<input type="text" id="player"><br />

<p id="welcome"></p>

<input type="button" id="ready" value="I'm ready">

<input type="button" id="deal" value="Deal cards">

<p id="opponents"></p>

<p id="cards"></p><p id="pack"></p>

</body>

</html>
```

And here's the JavaScript (place it between `<script></script>` tags):

```js
var ready = false;
$("#deal").attr("disabled", "disabled");
$("welcome").hide();
var socket = io.connect("http://1.1.1.1:1222");
$("#ready").click(function() {
  var player = $("#player").val();
  console.log(player);
  console.log('called');
  socket.emit("addPlayer", player);
  ready = true;
  $("#deal").removeAttr("disabled");
  $("#ready").attr("disabled", "disabled");
  $("#player").remove();
  $("#welcome").show();
  $("#welcome").text("Welcome, " + player)
  console.log("Ready:" + ready);
});

$("#deal").click(function() {
  if (ready) {
    console.log("dealing cards");
    socket.emit("dealCards");
    socket.emit("getOpponents");
  }
});

socket.on("showCards", function(cards){
  if (ready) {
    $("#cards").text(cards);
    socket.on("displayOpponents", function(opponent){
      $("#opponents").text("Your opponent is: " + opponent);
    });
  }
});

socket.on("remainingCards", function(remaining){
  if (ready) {
    $("#pack").text();
    $("#pack").text("Remaining cards are: " + remaining);
  }
});
});
```

We start with some standard jQuery calls to disable buttons we don't need yet. The interesting bit is the "I'm ready" button. We emit a message to the server and send the player's name as a parameter: `socket.emit("addPlayer", player);`, which maps to the "addPlayer" method on the server.

Here it is in action:

There are several issues with this version of the code. I know about them and I'll address them as I keep developing. Maybe by introducing other JS libraries. I've learned a lot about websockets (and JavaScript in general) while putting this together. Until next time.
