JAZOON'13 - Philipp Hofmann - Geek Jeopardy - The Making of

Embed Size (px)

Citation preview

The Making of

GEEK

Alain M. Lafon & Phil HofmannPanter AG, Zurich

Welcome to our talk The Making of Geek Jeopardy.My name is Phil Hofmannthis my colleague Alain LafonWe are working with Panter AGa 20 heads counting consultancy based here in Zurich.

How do we introduce ourselves best to a tech audience like you?

Please find the code here

github.com/branch14/geek-jeopardy

Our tech stack

Of course with a tag cloudpresenting the technologies we frequently work with.

As you can see there is a lot of Ruby going on,but also some other technologies.

At Panter we have awsome customers,but not quite as awesome as the one Ill introduce you to right now.

Imagine a client...

...who has the idea of an online version of Jeopardy.

Participants should be able to join the game with their smartphones, using their own devices to ring in to score points.

Imagine a client who has the ideaof an online version of Jeopardy.

Participants should be ableto join the game with their smartphonesusing ther own devices to ring in to score points.

Ok, who knows the rules of Jeopardy?

Ultra brief Rules of Jeopardy

3 Players, 1 Master

30 Clues: 6 Categories x 5 Levels

Player selects category & level

Master reads clue, Players ring in

Correct answers score points

Wrong or no answers cost points

The twist: Players phrase questions

1 game master3 contestants30 cluesdivided in 6 categoriesand 5 levels of expertise

a contestant gets to pick a cluethe master reads the cluethe contestants ring inthe first contetsant to ring in gets to answer the question

correct answes score pointswrong or no answers cost points

The twist: The answer has to be phrased as a question.

But, there is always a but

The client needs the App in about an hour.

Luckily, the client has a UI design team that is capable of producing markup

But the client needs the App in about an hour.

Luckily the client has a UI design teamthat is capable of producing markup

As you might have experienced yourselvesthis is not allways the case.

So how are we going to commence this.The title in the conferences program kind of gave it away: Well do pair programming.

Not like these guys.They are doing it wrong, obviously.

We will also be doing it wrong.But thats because were standing in front of couple of hundred people.

Our presentation will be held by the navigator (thats currently me)while the code will be written by the driver (thats currently Alain).

Since were short on time, weve to speed things up.We wont have time to get into too much detail.Nevertheless, this talk will require your full attention.I did not just have a coffee or are feeling otherwise not well preparedplease leave the room now.

Just kidding, please stay. (Pretty please stay.)

Like any good project well have a lot of talking in the beginningand a lot of coding towards the end.So Ill rush through the first chapter and I promise well slow down afterwards.

Chapter I

Basic Setup

Chapter I: Basic Setup

Next Steps

unpack markup provided

start revision control

specify and install dependencies

hack the backend

While my colleage will get right to it, Ill give you an overview:

unzip markup providedstart revision controlspecify and install dependencieshack the backend

Remember this will be mostly a frontend app,so the backend will be tiny.

Unpack & Revision Control

views

public

assets

git init .git add .git commit -m initial commit

Well unpack the markup and find three folders

views is where the html files arepublic is the directory where all the assets, mainly css, js, and images are located

while assets is a special folder which also holds assetsbut these are not meant to be served directly to the clientthese files need processinglike converting scss or sass into cssor translating coffeescript into javascript

Subsequently well start with the revision control. Here we use Git. If you havent done so you should check out Git.

This might seem a little too nitty gritty, but we really to join us from the beginning.

Moving on.

We need two components

Master (web)

Player (mobile web)

So we will need 2 componentsthe master with the game board and the cluesand a buzzer to ring in

So what are we going to use for the tiny backend.You saw the big Ruby in the tag cloud on the 2nd slide.So naturally well reach for one of Rubys web frame works.

Im not much of a designer. But I made this graphic for you.

Yes we could go with Rails.Who knows Rails? Yes, almost everybody does.But Rails is a little heavy weight on our tiny backend.So we could go with something more light weight like Sinatra.Who knows Sinatra? Ok, some.But still, we are looking for the minimal setup.

We only need the basics.

We really only need the basics.

So we will directly built on Rack.

Introducing Rack

Rack provides a minimal interface between webservers supporting Ruby and Ruby frameworks.

Rack is the common basis of 99% of Ruby web frameworks.

Its no much more than an abstraction layer on top of HTTP request & response.

Rack Data Structures

Request (List of Key Value Pairs)

{ PATH_INFO: /index.html, REQUEST_METHOD: GET }

Response (Array with 3 elements)

[ , , ]

Rack reduces the inner workings of a web app to very simple data structures:

A request is represented as a list of key value pairs.

A response is respresented as an array with three elements.The 1st element is a status code.The 2nd element are the headers which itself is a list of key value pairs.And the 3rd element is the content, which of course is optional.

Rack: use, map & run

There are multiple patterns to make use of Rack.

use, map & run are important keywords.

If you run an app thats an endpoint, of which you can have only one.But you can use multiple middlewares.A middleware can modify the any incoming requestas well as outgoing response.It even can short curcuit any request,returning an immediate response.

But you can also use map to map URLs or URL patterns to multiple endpoints.

Geek Jeopardy - Rack Config

We will be using a micture of both.

What you see here is the scematics of our tiny backend.

This is basically a diagrammatic version of the code in the config.ru file.

Chapter II

Introducing CoffeeScript & Faye

Thank you Phil and hello everyone.

Now that we have part of the backend in place, lets start with the frontend and something for the real time communication.

Btw, you are seeing Phil switch workspaces right now. This is because hes an Emacs wizzard while I prefer VIM.

But, we still like each other. That is actually possible^^

So to anyone out there who likes to engage in editor wars or any other kind of flame war: Be nice to each other. You all deserve it.

Next Steps

Code Ping

Jeopardy Exceptions

Explain CoffeeScript

Explain PubSub Pattern

Introduce Faye

Briefly Mention Reactor Pattern

Demo Ping

Our Jeopardy (some exceptions)

Teams (instead of single contestants)

After a wrong answer you can ring in again

No Timeout (timeout is handled by the host)

- Some noteworthy exceptions to the original game- adapted to a big crowd which will be separated in 3 teams

CoffeeScripts Basics

translates to JavaScript

borrows syntax from Ruby & Python

semantic white space

implicit return

CoffeeScript is basically an implementation of the best practices desribed in the book JavaScript: The Good Parts.

- In other talks you have seen ST-JS (Strongly Typed JS) and Typescript

- More on CoffeeScript we will show you later heads on with code

PubSub Pattern

- for the communication between master and player we chose the pubsub pattern- the pubsub pattern is a messaging pattern where messages are send via an event bus- to which the publisher can send messages- and from which the subscriber can recieve messages

- you can see a very simple example in this diagram

- but usually real world applications are not that simple- and thats why in our case the diagram will look more like this

Faye (Implementation of Bayeux)

- As you can see the master as well as the clients- act as both publishers and subscribers.- Thats because both need to send and recieve messages.

- I will illustrate that by explaining how the ping/pong mechanism works in the pubsub pattern.- The player will ping the master by publishing a message with its generated unique id to the event bus.- The master will have subscribed to these events to receive the ping.- The master will then respond to the player by publishing a pong message.- The player will have subscribed to the events of the server to receive the pong.- In our case the master will use the pong to inform the player about the team he has been assigned to.

- the implementation of the pubsub pattern we use is called faye.- faye is actually two implementations one in ruby and one in JavaScript for use with nodejs.- it makes use of the bayeux protocoll for formatting messages in JSON.- one nice thing about faye is that it ships its own JavaScript client library- which well load in the browser to be able to publish and subscribe with only a couple of lines of code

- for those who are curious: faye builds on eventmachine, which is a ruby implementation of the reactor pattern.

An Object Behavioral Pattern forDemultiplexing and Dispatching Handles for Synchronous Events

Implementation in Ruby: eventmachine

single threaded (in our case a good thing)

Reactor Pattern

- the reactor pattern is a pattern for demultiplexing synchronous events- and way to complicated to explain it here in detail.- but rest assured there is a white paper about it- (for those of you who like white papers)

- one interesting aspect of the reactor pattern is- that its explicitly a single threaded solution- which in our case is a good thing, right?- that way we let this beast answer the question- who was the first to ring in?

Demo

Ping Pong

Chapter III

Joining Players into Teams

Finally, now that most of the tech stack is in place, we get to the point where we actually implement some business logic.

Next Steps

Code some game logic

A word about jQuery

Briefly Mention RFC 4122

Demo some game logic

This is the chapter where I get to say anything I want. We just need the time to code.

jQuery - but why?

$.getScript(url, callback)

DOM manipulation vs. fancy Frameworks

Source: http://trends.builtwith.com/javascript/jQueryjQuery is the closest to a stdlib that JavaScript has.

jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.

$.getScript loads Faye client lib

Honestly I assume we could have saved a couple of lines of code by using AngularJS.

AngularJS has bidirectional data bindings as an alternative to direct manipulation of DOM.

We simply didnt wanted to pack more magic into this presentation.

Joining Players into to Teams

pseudo_uuid & localStorage

pseudo_uuid = -> # rfc 4122
p = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
p.replace /[xy]/g, (c) ->
r = Math.random() * 16 | 0
v = if c=='x' then r else (r & 0x3 | 0x8)
v.toString 16

get_uuid = ->
uuid = localStorage.getItem 'uuid'
uuid ?= pseudo_uuid()
localStorage.setItem 'uuid', uuid
uuid

- For those of you who know their RFCs well:- Yes, this is a rfc4122 version 4 compliant solution to implement generation of UUIDs.

- Honestly this was the only opportunity we found to bring a RFC into this talk.- Its not really needed.- We could simply replace it with a long enough random number.- But the code is so nice, dont you think?

Mention Stackoverflow

?= Existential Assignment (more or less unique to Coffee)? Existential Operator

Demo

Join Players in Teams

Chapter IV

The State Machine &Some CoffeeScript Details

First of all congratulations you all made it to chapter 4- our final chapter.

The title gives it awayto implement the rest of the applicationwe go with a state machine.

Next Steps

Code the State Machine

Explain the State Machine

Some CoffeeScript Details

Demo the whole game

So naturally the next steps areleading to the State Machineand walking you through the details of it.

Secondly I would like to highlight some noteworthy parts of the CoffeeScript.

And if everything goes smoothlywell use the time when you usually get to ask any questionto demo the app.

Jeopardy in Single Steps

A clue is selected

The clue is read

No buzz is received

Buzz is received

Answer is correct

Answer is wrong

These are all events.

If try to split the game into single stepswe might end up with something like this.

A clue is selectedThe clue is readNo buzz is receivedBuzz is received

These are all eventsand events usually make good transitions in a state machine.

Who has used a State Machine before?Who has never used a State Machine before?

So if Id draw a diagram for the jeopardy state machine it will look like this.

Jeopardy as State Machine

4+1 states6+1 transitions

4 states and 6 transitionsthe plus 1 is for the state initialize, which isnt really part of the game.

Ok, a State Machine - but why? wiring the logic for the game without a state machine, will simply be futile.It will inevitably lead do lots of horrible, unmaintainable code.Weve all been there, dont feel bad.

By thinking of it as a state machineyou gain a better structure.Youll easily discover edge conditions.And if you use a state machine libraryyou can make use of guards, which prevent invalid transitions,and you can define callbacks on transitions.

Putting this diagram into code will probably look like this.

State Machine in JavaScript

events: [
{ name: 'start', from: 'initialize', to: 'select_clue' },
{ name: 'clue_selected', from: 'select_clue', to: 'read_clue' },
{ name: 'clue_read', from: 'read_clue', to: 'receive_buzz' },
{ name: 'buzz_received', from: 'receive_buzz', to: 'receive_answer' },
{ name: 'answer_wrong', from: 'receive_answer', to: 'receive_buzz' },
{ name: 'answer_correct', from: 'receive_answer', to: 'select_clue' },
{ name: 'no_buzz', from: 'receive_buzz', to: 'select_clue' }
]

https://github.com/jakesgordon/javascript-state-machineAn event is a transition from one state to another.If it looks like this youre luckysince this is the formatthe JavaScript State Machine library by Jake Gordon expects.

This basically defines the transitions from one state to another.

The state machine will only be able to perform transitions defined here.And it will do so by calling methods on the State Machine Instancenamed after the names of the events.

So the only thing left...

Callbacks on Transitions

onanswer_correct: -> faye.publish "/state/#{active_player}", state: 'inactive' scores[players[active_player]] += board[active_clue].value show_scores()

onbuzz_received: (event, from, to, data) -> active_player = data.uuid team = players[active_player] $("#team-#{team} .team").css color: 'red' $('#controls').show() $('#no_buzz').hide() faye.publish "/state/#{active_player}", state: 'active'

is to define the side effects of the state transitionsas callbacks to these events.

These are just 2 examples.

The 1st one onanswer_correct will send a signal to the active playerto go back into state inactive.Then it will add score points for the players team.And finally it will trigger to update the scores on the view.

The 2nd example is fired when a buzz is received.This of course as its own side effects.This event makes the state machinetranscend from the state receive_buzz to receive_answer.

Whenever a player hits the buzzerthey faye client on the masters sidewhich subscribed to these eventswill trigger this transitions.

But the transition will only take place ifthe state machine is in state receive_buzz.

And thats when the state machine acts a guard.

(Ask Alain how the coding is going.)

Next up: CoffeeScript details

Thats more like a note to self.

Alain how is the coding going?

Ok to give Alain a couple more minutesI would like to focus your attention to some CoffeeScript details.

Function Definition & String Interpol.

faye.subscribe "/pong", (data) ->
util.log "pong received with Team #{data.team}"

faye.subscribe("/pong", function(data) {
return util.log("pong received with Team " + data.team);
});

First up: Function definitions & String Interpolation

Function definitions, especcially for annonymouns functions is something you need fairly often in JavaScript.That is why CoffeeScript provides a handy shortcut: the arrow with paramater definition prepended.

What JavaScript is entirely missing is a handy String interplation.The Syntax is obviously stolen from Ruby.

Named Fields

faye.publish("/pong/" + data.uuid, { team: team });

faye.publish "/pong/#{data.uuid}", { team }

Next up: Named Fields.

Thats also something you come across fairly often when writing JavaScript.When your variable is identically named as the field in an object you want to createyou get this somewhat awkward redundancy.

CoffeeScript again provides a handy shortcut.

List Comprehensions

var team_counts;

team_counts = function() {
var counts, k, v;
counts = {a:0,b:0,c:0};
for (k in players) {
v = players[k];
counts[v]++;
}
return counts;
};

team_counts = ->
counts = {a:0,b:0,c:0}
counts[v]++ for k, v of players
counts

And last but not least: List Comprehension.

So many fine languages have list comprehensions.CoffeeScript brings those finally to the JavaScript eco system.

The suffix notation, you see in this example, is a matter of taste.You can also use it in a more common prefix notation.

But if used carefullyyour code gets so much more succinct.

And if you get used to it,its definitly one of the things you will ask yourselfhow programming without was even possible.

These were actually my finishing words.Lets see if Ive to buy us some time.

Demo

The whole game

Shameless Plugs

Panter is hiring.

If you want to work with usspeak to us.

[email protected]@dispatched.ch

Linkbait

Geek Jeopardy: github.com/branch14/geek-jeopardy

Used technology:

Rack: rack.github.io/Faye: faye.jcoglan.com/Bayeux: svn.cometd.com/trunk/bayeux/bayeux.htmlEventmachine: rubyeventmachine.com/

Click to edit the title text format

Click to edit the title text format

Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline Level

Click to edit the title text format

Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline Level

Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline Level