Heidegger, in retrospect

My last project at the Entertainment Technology Center at Carnegie Mellon was Heidegger, at our Silicon Valley campus. The client was Electronic Arts and we were very lucky to be able to work with several people from the Dead Space team at Visceral. Our project was about finding a way to deduce player types though gameplay analytics and from there predict how likely people will be to like another game.

I worked on the interface with the very talented Anabelle Lee. She took care of aesthetics and I was in charge of functionality. I took that opportunity to improve my skills with the HTML 5 Canvas and jQuery. But, most of all, I got to experiment with Websockets and the fascinating Tornado web server, written in Python.

I also wrote and edited our promo video. I did not film it, though. That part went to other members of our team.

I would like to take the opportunity to thank Ben Medler, our fantastic client contact for just being so awesome.

A webserver optimized for websockets

As part of my OCCO project, I made a web server that makes the use of websockets easy. I din’t make it from scratch, of course, I made it with Tornado. Tornado is a very lightweight, flexible and extensible web server written in Python. It makes the use of websockets trivial.

My whole code is on GitHub:

https://github.com/eje211/heidegger

This site is a mockup of a modification of the interface of Electronic Arts’ Origin game distribution system. My team added a panel that informs the player of their Bartle player type. My websocket feature allows me to change the player type in real time during presentations. This was really made to have a good reason to use websockets more than anything else. The Javascript part of websockets never changes. It’s the part that’s on the server that’s often problematic. In this case, I have a page with the player type chart and one or more pages with a remote controller to change it. The code to handle this is absolutely trivial:

CHARTS        = []
CONTROLERS    = []

class ChartHandler(tornado.websocket.WebSocketHandler):
    '''
    Set up a connection to the chart. We won't be receiving any
    information from it, just sending some.
    '''
    def open(self):
        CHARTS.append(self)
    def on_message(self, message):
        pass
    def on_close(self):
        try: CHARTS.remove(self)
        except ValueError as e: print('Could not remove chart handler:', e)

class ControllerHandler(tornado.websocket.WebSocketHandler):
    '''
    Get every change from each controller and send it back to all the other
    controllers, if there are any. That way, if other controllers make a
    change, it will include the ones made by other people.
    '''
    def open(self):
        CONTROLERS.append(self)
    def on_message(self, message):
        for chart in CHARTS: chart.write_message(message)
        for cont in filter(lambda x: x != self, CONTROLERS):
            cont.write_message(message)
    def on_close(self):
        try: CONTROLERS.remove(self)
        except ValueError as e: print('Could not remove controller handler:', e)

I keep a list for each of the two types of websocket handlers and keep them updated as the sockets are connected and disconnect. And, as message come, I just pass them along to the relevant pages. That’s really all there is to it.

Tornado also requires me to deal with the delivery of files manually. That was new to me, coming from Apache, Lift and Zope. It was interesting and made me aware of many details.