DEV Community

loading...
Cover image for Coding a Planning Poker app

Coding a Planning Poker app

lukegarrigan profile image Luke Garrigan ・4 min read

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

Image of planningpokeronline

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);
Enter fullscreen mode Exit fullscreen mode

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}`});
});
Enter fullscreen mode Exit fullscreen mode

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;
  }
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
  }
Enter fullscreen mode Exit fullscreen mode

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);
  }
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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', () => {
  this.showVotes = true;
})
Enter fullscreen mode Exit fullscreen mode

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/ 🚀

Discussion (2)

pic
Editor guide
Collapse
hey_trey profile image
segreus

I've never heard of this term before, which is strange, since I often play in crypto casinos on the site here. This may not be so useful information for me, but still thank you for sharing. I believe that any information is important and necessary. So I read a lot of different articles on the Internet. Thank you again.

Collapse
lukegarrigan profile image
Luke Garrigan Author

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.