jazoon'13 - philipp hofmann - geek jeopardy - the making of
Post on 16-Apr-2017
575 Views
Preview:
TRANSCRIPT
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.
phil@branch14.orgalain.lafon@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
top related