My Three Words
(3 minute read)
I'm currently doing some work for Miura, a digital design agency based in London. A month ago the creative director came up with a silly but fun idea: "how about a page where different people can come in and type in 3 words a time, building up a short story?". I told him I could probably knock up a prototype within an hour though I didn't think he'd want me to actually do it!
So I wrote a cheap and nasty PHP script which stored the input in a local CSV file. Once the page loaded it would fetch the existing story data via AJAX (using jQuery) and the user would submit new data using a simple form at the bottom. We had a quick play around with this in the office and it was quite amusing. Because the AJAX fetch would run only once every 5 seconds you'd often finish inputting your 3 words to continue the story only to find that someone else had already beaten you to the punch. So the story ended up not making much sense but I think this actually made it funnier, especially given how quickly everything disintegrated into a discussion about pooh and other lowbrow stuff (tells you a lot about us, doesn't it?).
After this successful "pre-alpha" in the office we decided to build it properly and make it public - mythreewords.com. Here's how it works. The active story is always at the top. You can enter 3 words at a time, no more no less. And you can't have URLs or HTML tags in your words. If you end your last word with a ?, . or ! then you complete the active story and it gets shifted below. A new story is begun with the first 3 words auto-generated by the system.
Completed stories have a button next to them which allows you to tweet them through your Twitter account (if you have one). Since tweets have a 140-character limit we truncate the story if necessary and insert a link back to the full version of the story using a short alias domain (m3w.in):
For the public release I rewrote the original codebase using Kohana 3 for the framework and MySQL for storing the data. I investigated AJAX Comet techniques and settled on using long-polling to simulate data push from the server to the client. This means is that as soon as someone else adds their three words all the other clients are almost immediately updated.
To further increase performance the system does not write anything to the database until the active story has been completed. Until that point everything is stored in a memcached instance running on the same machine. Once the active story is completed by a user it gets marked as such and a new active story gets created and cached. A cron script running every 60 seconds then processes all completed stories by inserting them into the database (and subsequently removing them from memcached).
I also had a go at providing notification when other users are typing. How it works: when the page loads it generates a unique id. When the user starts entering words into the input field an AJAX call is made to the server which this unique id. The server then stores all such submitted unique ids together in a an array in memcached. Changes to this array are pushed to all clients (using the Comet technique mentioned above) who then indicate how many users are currently typing:
Only upto 5 unique ids are stored on the server so that the array search complexity never exceeds O(5) (clients show this as 4 typing). The array data is automatically cleared after 5 seconds of no change to avoid stale data. And clients don't inform the server that they're typing more frequently than once every 5 seconds.
If you want to understand the internal workings of the site better use Firebug (or your preferred tool) to eavesdrop on the AJAX calls.
So that's the sum total of the site for now. Implementing it was a lot of fun. I hope you enjoy it too :)