Luke Garrigan

Posted on

# Coding a Planning Poker app

The 2 week sprint is over, the scope for the next sprint has been established by management, it's time to estimate. Many programmers will likely have to go through the process of estimating the next chunk of work to get a feel for how much of the chunk can be done in the next couple weeks.

There are many ways to go about estimating, using the Fibonacci sequence, the modified Fibonacci sequence, t-shirt sizing esimating, etc. My team tends to go for the Fibonnaci sequence to measure the complexity of tickets in order to story point.

Once upon a time in a not-so-digital world, one might use physical playing cards to do the estimation. But now, we have no choice but to use software to fill the void! My team tend to go for planning poker apps like planningpokeronline.com

Where members of the team choose the card they think represents the complexity of the ticket in question and then at the end - when everybody has voted - the cards are turned and the estimations shown, followed by a discussion on why people chose said card.

Anyway, planningpokeronline.com is indeed a great app, but it only allows you to play a certain amount of games before trying to sell you the premium version, which does my bloody head in.

So this week, I decided to create my own, free version.

# My planning poker app

At the time of writing this blog, I've got the app deployed at lukegarrigan.github.io. You should be greeted with a button and nothing else, no fluff.

When you click Start new game a socket connection is established with the server - currently hosted on heroku. When the socket connection is made the server makes use of socket.io's rooms, which is a server-only concept that allows us to split sockets into an arbitrary channel. I generate an `id` using short-uuid to represent a room, this `id` is then passed back to the front-end which then handles the routing.

io.on('connection', (socket) => {
console.log('a user connected', socket.id);

``````let roomId = socket.handshake.query['roomId'];
if (!roomId) {
roomId = short.generate();
socket.emit('room', roomId);
}
socket.join(roomId);
``````

As shown above the server emits a room event `socket.emit('room', roomId);` passing along the generated `id` back to the front-end. The front-end then stores the socket connection to state, which is just vue.js state management library. Then we route the user to the path `game/\${roomId`}.

``````const socket = io(process.env.VUE_APP_SERVER);
store.commit("setSocket", socket);
store.state.socket.on("room", (roomId: string) => {
router.push({ path: `game/\${roomId}`});
});
``````

Something like this:

Then you're asked to enter your name:

When you hit enter the front-end emits a name event for the server to pick up:

``````  public enteredName(name: string) {
store.state.socket.emit('name', name);
this.modal = false;
}
``````

The server then emits this information to all players in your room:

``````function updateClientsInRoom(roomId) {
const roomPlayers = players.filter(p => p.roomId == roomId);
io.to(roomId).emit('update', roomPlayers);
}
``````

But of course, in our scenario, there are no other players to send the information to as we've created a new game with the intention of inviting our team to play!

Let's invite our team by clicking the Invite players button:

A little bit of hacking was needed to get this to work on the front-end. In order to copy something to the clipboard the value that is to be copied must be within an input tag. My button is quite clearly not an input so I had to create a temporary input which gets appended to the body, the value of the current URL is put into that input - `window.location.href` - we then copy the value to the clipboard and finally remove the element.

``````public copyToClipboard() {
const tempInput = document.createElement("input");
tempInput.value = window.location.href;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
this.showCopiedToClipboard = true;
setTimeout(() => this.showCopiedToClipboard = false, 3000);
}
``````

So, go ahead and send the link to your team!

So Bill is quite eager and dished out a vote quite early:

That vote is sent to the server through our socket connection:

``````  public performVote(vote: string) {
store.state.socket.emit('vote', vote);
}
``````

And then subsequently sent to all the clients in the room so they can see that Bill has voted:

``````socket.on('vote', (vote) => {
let player = players.find(p => p.id == socket.id);
if (player) {
player.vote = vote;
}
updateClientsInRoom(roomId);
});
``````

When we've all voted, it's time to show the votes. Let's click Show Votes!

This follows the same process as above, sending a 'show' event which gets sent to all clients and upon receiving the event on the front-end we set `showVotes` to true which just makes the votes visible:

``````store.state.socket.on('show', () => {
})
``````

Jeez, turns out Elon is pretty optimistic when it comes to estimating, who'd have guessed?

And that's pretty much it for this week's hack, it's been fun to make something I might actually use more than once! Hope you've enjoyed the blog, follow me on Twitter https://twitter.com/luke_garrigan where I just talk even more dribble!

If you enjoyed this blog I write quite a bit more on http://codeheir.com/ ðŸš€

## Top comments (6)

Rala Volo • Edited

I myself am from Latvia and I remember looking for a good casino where you can play poker and so on. It turned out to be a very difficult task and I certainly thought about how to solve this problem. Luckily then I found ggbet casino and I was very lucky that I did. Now I will be able to bet normally and make a profit reliably.

Luke Garrigan

Thank you for the comment, it's not a gambling app however, it's just means for software development estimation. So, you have a chunk of work that needs to be done, you estimate how long it'll take to do that chunk of work, you take the average scores of the team to point the ticket.

AustinJohnson1

Yeah, I agreed with you.