PhoneSimon and PhoneSimonPWN - A Twilio Game in PHP

As mentioned in my previous Twilio post, I started playing with Twilio apps this week after being inspired to enter the current Netbook Contest. This week’s category is PHP. I tried to think of an application to enter that would be quick, simple, elegant, and fun for other people to use. I came up with the idea of creating a Simon game to be played over the phone by using the touchtones as the game sounds and called it PhoneSimon. In about 3 hours Monday night, I was able to have a working version of the game complete with a leaderboard on my website to keep track of scores.

Tuesday morning I started talking about my little creation over Twitter, and it even got some notice on a Hacker News thread. By the end of the day, I had:

I thought that this game would be a very solid entry to the contest. I was pretty happy.

Imagine my complete and utter shock when I discovered that a very similar Simon game (called Similio) had already won the Twilio Netbook Contest during week 6! Oh, No! This was completely my fault for not doing my homework to see all of the previously winning entries, but I felt pretty bummed. I was feeling like my chances of winning were shot unless I could cook up something additional to enter along with PhoneSimon.

I was very surprised to see that PhoneSimon turned out to be so similar to Similio (though they do have differences) regarding the fact that they were developed independently of each other. Great minds must think alike!

Still, I felt to be competitive and original in the contest, I needed to add another element. What to do?

After playing the game myself many times, and watching others play and post their scores, we all noted that the insane level (digits 0-9) was, in fact, very very difficult. One player (@mcav) managed to post two very impressive scores of 8 correct digits on the insane level. He later explained that he is a jazz pianist, and that helped him hear the intervals in the DTMF tones.

Then I thought, what if I could write a secondary Twilio application to actually play PhoneSimon autonomously and get a “perfect” score on the insane level? This was to be my extra piece to the puzzle. I would call it PhoneSimonPWN because it would blow away all other scores on the insane level.

Over the next few nights I struggled with a way to make this work. I created an application that would Gather and Play tones, but I tried to make it work by holding two phones up to each other (in reverse orientation) so that they would listen/talk to each other. This proved to be problematic because the quality of the DTMF tones coming out of the phone speakers was degraded, and the fact they were entering a microphone of less than stellar quality meant that the tones had a very low success rate of being registered by the Gather commands on either end.

After reading through the Twilio API docs, I was intrigued by the ability to place outbound calls from the Twilio call centers. This seemed like a prefect mechanism to connect one application to another through a single circuit connection (instead of coupling analog phones together). The problem then became, how do I listen in on the call to make sure it is working as planned? Well, you can’t, but I could watch the webserver logfiles of the Twilio application files being served. I added some extra logging information in the PHP scripts to dump out actions being taken at each step so I could follow along as the call happened. It turned out that this worked perfectly. Too well, in fact. I had to put a statement in the PhoneSimonPWN to intentionally lose after a while or it would continue on forever.

You can still play PhoneSimon right now if you want. Go ahead and give it a try!

Below is a screencast video demonstrating how the whole system works; more specifically, how the PhoneSimonPWN system works and interacts with the PhoneSimon game itself. There is some weird video artifact in the beginning of the video where the website bleeds through the terminal window I used to initiate the outgoing call, but that clears up after several seconds. Make sure to watch in fullscreen to see all the details. Following the video is all of the code used to create PhoneSimon and PhoneSimonPWN.

Screencasts and videos online

PhoneSimon Code

dbonline.php

dbonline.php is an include file to allow the PhoneSimon application to connect to my database for retrieving usernames based on pin numbers, and it allows storage of games scores back to the database.


1.php

This is the beginning of the PhoneSimon menu system. It asks the player if they have a username pin number or if they wish to play as a guest. The result of this question is POSTed to 2.php.


2.php

2.php checks the result of the question from 1.php. If the player has a pin, it asks for 4 digits and POSTs the results to 3.php. If the player is playing as a guest, it assigns them a random Guest name and sends them to 4.php to choose a difficulty level.


3.php

3.php checks the validity of the player’s pin number and looks up the associated username. Then, they are sent to 4.php to choose a level of difficulty.


4.php

4.php asks the player to choose a level of difficulty. The username is passed along through this step in the query string to 5.php.


5.php

5.php checks the level of difficulty selection and starts the actual game by Redirecting to round.php. All game state information is passed through the query string.


round.php follows

round.php is the main game engine. Since Simon is a very repetitive game (play some tones, listen for some tones), it basically just needs a main game loop to run. round.php acts as this game loop, POSTing back on itself after each round to continue the game. If the game is ended by an incorrect entry, the score is recorded and the player is sent back to 4.php to choose a level of difficulty to play again.


PhoneSimonPWN Code

The following two files make up the entire PhoneSimonPWN application. The PhoneSimonPWN application is connected to the normal PhoneSimon application because of the outgoing call made by the Twilio API to my sandbox number. The pwn.php file then connects to my sandbox account by playing the correct pin number, then it uses a series of Pauses and Plays to step through the PhoneSimon menu system automatically. Along the way, it enters in the “SimonPwnr” username pin so that the username will appear on the leaderboard after the game is done. When the PhoneSimon game starts, the end of the pwn.php file Gathers the initial tones and POSTs them to the pwn2.php file.

The pwn2.php file basically acts as a loop. It takes the POSTed digits from Twilio (from the previous Gather) and plays the tones back over the line. This is the equivalent of a PhoneSimon player pressing the buttons repeating back the tones during a round of the game. Then there is a Gather which listens for the next round of tones, which get POSTed back to pwn2.php again. This could continue forever, but there is a piece of code in pwn2.php which will end the game once a certain score has been reached. A score of 30 takes about 8 minutes to achieve, so this is where I cut it off. The pwn2.php file will play the digit 0 followed by # to automatically fail the round. The game ends, and PhoneSimon records the score and displays it on the PhoneSimon Leaderboard.

This is the API call used to initiate the call between PhoneSimonPWN and PhoneSimon:

curl -k -u "AccoutnSid" -d "Caller=8665836913&Called=8665836913&Url=http://twilio.jazzychad.com/phonesimon/twilio/pwn/pwn.php" https://twilio.com/2008-08-01/Accounts/AccountSid/Calls

pwn.php


pwn2.php


Twilio - Register the Sandbox Number as an Outgoing CallerID

I just started using Twilio this week after being inspired by seeing other entries in their weekly Netbook Contest. I started making different applications to learn the API. One of the cool parts of Twilio is being able to make outboud calls from Twilio’s phones. Once the call is picked up by the receiving party, your custom application is run for the receiver to hear. Cool!

As part of the API, you are required to set an outgoing CallerID number (which will show up on the receiver’s CallerID information). At first I left this blank, but the API returned an error saying I needed to specify one. So, since I was using the Twilio sandbox number, I put that number in next. Again, the API call failed with an error that “this number is not listed in your outgoing CallerID list.” This was true. I had assumed that outgoing calls would automatically be allowed to use the sandbox number, but I guess I was wrong.

I registered my own personal cell phone number as an outoing CallerID number, but I wasn’t too thrilled to have this number show up on CallerIDs for my test applications. I wondered if there was a way to register the Sanbox number. There was no way to do it through the Twilio site, so I would have to do it manually… but how?

To register an outgoing CallerID number with Twilio, you have to enter the number you wish to use and click the “Add” button. Then Twilio will call the specified number and display a series of digits you need to enter when you answer the call. This is to verify that you do, in fact, have access to this number and can use it to place calls.

While working on another application (PhoneSimon), I realized that I could play DTMF touch tones over the line. Then it hit me. I could use the same technique to play the verification code back to Twilio to register the Sanbox number. Thus the register.php script was born.

Play the video below (in fullscreen mode for full effect), and look at the register.php code below that to see how it all works. If you want to do the same thing, just copy the register.php code onto your webserver and use its address as your sandbox account URL. Just make sure to set the address back to your application URL after you are done!

Click here to download the set of DTMF tones as wav files

Screencasts and videos online

Twitter DM Email Parser Script

This post originally appeared on my startup blog at http://bootstrapd.me/?p=550. It is copied here since it is code related.

Since I am now my own sysadmin for the various servers I have running, I have forced myself to learn how to setup and administer mailservers on linux boxes. Now that I have that under control, I can also write scripts to parse and interact with incoming/outgoing email. My first such foray into playing with email scripts was to create a Twitter DM parser which strips incoming Direct Message emails from Twitter and re-formats them down to the bare essentials and forwards the resultant information back to my main email address. After that was working, I had the idea to give myself the ability to reply to these emails in order to send a reply DM back to the original sender. This system turns out to be really handy, thus turning Direct Messages into another form of email.

It used to be that all Twitter-generated emails were plain text. No HTML markup, no images, just text. All was right with the world. I’m not sure what it is, but I just believe that all email should be plain text. HTML is for the web (this is a poser since I read my email in GMail which is itself a web-based email client…) Outside of GMail I like to use pine (now alpine) which probably explains a lot. Anyway, here is a screen shot of an old format Twitter DM email that I found (note the date):


twitter-dm-gmail-plaintext


Some time in early 2009, the Twitter-generated emails changed to HTML formatting:


twitter-dm-gmail


The whole message of the DM is hello, there jazzychad! which is all of about 23 characters. In order to deliver that Direct Message to my inbox, the email itself is a couple of kilobytes big. Here is the source:


twitter-dm


You might say, “A couple of kilobytes? Who cares! Plus, it looks pretty.”

You may be right, except that I am not always at my computer (a shame, I know) and might receive email on my phone (which still uses Edge) and so any extra unneeded bytes (especially the 3 extra images that load) are manifested in extra download time waiting for an email to load:


iphone-twitter-dm


Whether receiving the Direct Message email on my computer or my phone, if I want to respond I have to leave the email client and use another program/site/twitter client to create and send a reply DM. On my phone this is cumbersome to say the least; on the computer it’s not so bad since I usually have another twitter site/client open, but it does break the flow of reading/responding to my emails. I do a lot of correspondence over DM (maybe more than I should), and the time spent bouncing back and forth adds up.

So, how do I fix this problem? Write a script, of course!

I have setup an email filter which automatically forwards Direct Message emails to a special email account on one of my servers where it then is processed by a PHP script. The original DM email is archived and my script parses the Direct Message email for the important bits (highlighted by red boxes in the above email source screenshot), creates a new email and sends it back to my main email address. The resultant email looks something like this:


mailbot-dm-gmail


Just the facts, ma’am. The source for the email, while not tiny (because of the email headers) is still much smaller than the HTML-ified original:


mailbot-dm


The email gets straight to the point and also loads quickly on my phone (especially without images).


iphone-mailbot-dm


This was great until I realized that I still had to bounce to another application to reply! What if I could just reply to the email itself and have it deliver the message as a DM to the original sender?

I added a bit more logic to my PHP script so that it knows the difference between an incoming DM and a reply DM and can take action accordingly. Now I can just click “Reply” in the email and send a DM. I have gotten to the point where I know what 140 characters “feels” like (sad, but true), so I’m not worried about going over the limit (though I think the DM limit is unofficially 255 characters).


mailbot-dm-gmail-reply


I click “Send” - et voilà! The reply is delivered.


twitter-dm-sent


An added bonus is that I now have a conversation thread saved in my email. As of this writing, there is no way to see the link between DMs on the Twitter site or through the API like there is to see the link between tweets and their replies. Being able to reply to an email gives me context when I need to go back and look at a conversation later.

The one thing I have yet to add to the email script is the ability to originate a DM to somebody. That is, send a DM without replying to somebody who DM’d me first. This would be easy enough to add, I just need to come up with some sort of subject line format which would tell my script to just DM this person. For now, the DM mechanism on TweetGrid allows me to do this easily enough when I’m at my computer. Being able to originate DMs by email would be especially handy on my phone.

Is the script perfect? No, probably not, but it works for me. If you’d like to have a look and play around with it, here is the source code. It requires the PHP Pear mimeDecode module.

If you have a mailserver and it supports a ~/.forward file, you can put the following line in it to pipe the email to your script:

“|/home/username/path/to/script_filename.php”

Just make sure to make your script executable or the pipe will fail.

No Twitter Trending Bots - Greasemonkey Script

First, the good stuff.  You can read the backstory down below.

Script:

http://jazzychad.com/twitter/notrendingbots.user.js

If you are using Greasemonkey in FireFox, you can click the above link to install the script.

What does it do?

This Greasemonkey script will remove tweets by the Twitter Trending Bots from the http://search.twitter.com/ search results. Right now that list includes:

If you are searching a trending topic, you don’t need a dozen bots telling you it’s trending. You already know that!

However, if you are specifically searching for one of these bots, the results will remain intact, just in case you want to use one of them to see the history of trends.

If any tweets are removed from the results, a little blue info window on the results page will tell you how many.

Screenshots:

No Trend Bots - screenshot 1


No Trend Bots - screenshot 2


For people who know how to edit user/greasemonkey scripts, there is a sections that looks like this:

trendbots.push(”tweet_trends”);
trendbots.push(”realtimetrends”);
trendbots.push(”twopular”);
trendbots.push(”twopularfeed”);
trendbots.push(”twopularalert”);
trendbots.push(”twithority”);
trendbots.push(”attrending”);
trendbots.push(”trending”);
trendbots.push(”tweetingtrends”);
trendbots.push(”retweettrends”);
trendbots.push(”daymix”);
trendbots.push(”trendingtopics”);

Feel free to add/delete other bots/accounts from that list to suit your taste.

Backstory:

Earlier this week, I launched a new twitter bot @RealTimeTrends which tweets when new trends appear and when currently existing trends move up in ranking.  I found this to be more informative than the other existing trend bots.  Also, I use it as a way to link to my TweetGrid Search site.  Now, I have always felt that these sorts of bots were kind of spammy, but when I launched mine, I quickly found that lots of people click the links attached to those tweets… a suprising number, in fact.  So, obviously people find this sort of information useful.  My bot even has around 100 followers so far (in under a week, as of time of writing). Update: After 1 month it has 765 followers. *boggle*.  I try not to let my bot be too verbose.  It only tweets new and rising trends, not the entire list of trending topics every 5 minutes (which is how often twitter updates its trends list) like many of the other trend bots.

Suddenly I received a tweet to my bot from @gregorylent assailing its service:

@RealTimeTrends really sorry to see your service, you just add fog to twitter search ..

Link to original tweet

Apparently he was going after the other bots, too:

@twopularFeed what is your reason for being, i go to a topic to read about the topic, not to read your summary .. please get a job

Link to original tweet

I can’t say that I blame him, but like I said, it drives traffic so I’m certainly not going to turn it off.

So why write this greasemonkey script? Two reasons, really.

1. It occurred to me that the problem of removing trending bot tweets from search results could be easily achieved with a quick greasemonkey script.  I had never written one before, so I took the opportunity to learn how.  It was quite fun, so I think I’ll be writing some more in the future.

2. Even though my bot works, has followers, and even gets retweeted (another surprise), I still felt it was all kind of spammy.  I felt like writing this sort of script would even things out.  I am providing a bot to be informative, but I am also providing a mechanism to shut it up (along with others).

There you have it.  As more bots come along I will try to keep the script updated.

When Cluster Computing Can Slow You Down, and How To Optimize It

I have long been fascinated with the concept of cluster (or distributed) computing.  Projects like BOINC and Folding At Home that take advantage of millions of people’s idle computer cycles are brilliant.  I have several computers in my house that I use for various purposes, but they are rarely ever all being used at the same time.  I always wanted to try to run some sort of clustered application across them but never found a great reason until recently: making DVD backups by transcoding them into xvid files.

There is a great program for ripping DVDs in linux called dvd::rip.  It it written in perl and is very easy to use if you are comfortable with a linux/console environment.  One of its great features is the ability to transcode ripped DVDs by creating a computer cluster out of your networked computers.  Before I get into the details, let me step back and give a very brief overview of the basic way a computing cluster works.

Read more

The Ultimate Twitter Search Widget

I have released a Twitter Search Widget and supporting API for use on any website. You can find it here:

The Ultimate Twitter Search Widget

These widgets display tweets based on the search.twitter.com API and can be customized with great flexibility. Go check it out!

Initial Google Chrome Memory Usage Comparison

Before you flame me, I know that Google Chrome is early early beta, but I find this kinda silly. Bragging about your superior memory management means it should have superior memory management. After installing Chrome and firing up my 4 most frequently loaded pages in 4 new tabs, I notice that things started to get clunky. I open up Firefox 2 and open the same 4 pages in 4 new tabs and compare. In Chrome you can open ‘about:memory’ to see memory usage statistics (which is pretty awesome). Anyway, this is what I see:

chrome_mem


Chrome is using almost twice what Firefox is using. If you’re interested, here are the 4 sites:

Now, I know that RAM is there to be used, and maybe I’m missing some point of what Chrome is trying to do at the moment (I know that the comic book said that it tries to amortize the memory cost of a tab up front at its creation), but yikes… this is a tab tad concerning…

Hurricane Gustav Twitter Tracker

At the suggestion of waynesutton, I have created another twitter tracking site. This time it is for Hurricane Gustav related tweets. There are a few filters available to narrow down the results on each page.

Hurricane Gustav Twitter Tracker

UPDATE:

I also created a widget you can install on your site/blog at http://jazzychad.com/twitter/gustav/widget.php

In the first 24 hours, over 32,000 widgets were served.

You can see it in action at these sites (probably until Gustav blows over):

Sarah Palin Little Known Facts

Today John McCain announced Alaska governer Sarah Palin as his candidate for Vice President.  No sooner had the happened than @MichaelTurk inadvertently started the newest internet viral (micro)meme on twitter: “Little Known Facts: Sarah Palin” His unassuming tweet, “Little known fact: Sarah Palin used to wrestle kodiak bears in Alaskan bare knuckles fight clubs.” set off an explosion of other twitter users coming up with their own Chuck Norris-style little known facts about Palin.  MichaelTurk is keeping a log of some of these little known facts over at his site http://www.palinfacts.com/

During the next few hours, over 1,000 little known facts were tweeted (perhaps not all unique), but the point is how quickly this caught on like wildfire.

Since you can only see up to the most recent 100 tweets on search.twitter.com, I decided to write a tweet collecting engine (similar to the one used for FlixPulse.com) to keep a catalog of these little known facts. The results are shown at http://jazzychad.com/twitter/palinfacts/ In just under 2 hours, I have collected over 200 little known fact tweets. Amazing.

During the first few hours, all of the tweets were positive in Chuck Norris fashion.  Then all of the sudden I started to see some negative ones creep in.  It seemed that those who are unhappy with McCain’s choice, and some Obama supports, figured out that two can play at this game.  Still, the overwhelming majority are positive in nature.

I see that even as I write this post, Turk from palinfacts.com has added a link to my database site on his blog.  Thanks, Turk!

Who knows how long this will keep up, but I will keep logging the tweets as they come in!

Barcodes Are Fun

I have always been fascinated by barcodes and the various methods to encode human readable information into a machine readable format. A long time ago I found a great little program for my TI-89 calculator that would draw a user-entered UPC code onto the graph screen. I ported it to work in Windows using Visual Basic to gain an understanding of how barcodes are created. I even went so far as to use my CueCat to scan barcodes on products and have my program automatically reproduce the bardcoce on screen.

Later on when I was learning to use the gd library for image creation within php scripts, I decided to start by porting the barcode generator once again. I never got it quite right, but I had learned enough to move on with whatever project I was working on. Recently I stumbled upon that old barcode gd script and decided to fix it so it worked correctly.

First the barcode creator only generated UPC-A barcodes (the big 12-digit codes you scan at the check-out line). After getting that to work successfully, I decided to implement UPC-E barcode generation as well. UPC-E codes are usually found on soda cans or snacks and only have 6 digits so they take up less physical space on the product.

UPC-A and UPC-E Barcode Generator

If you should ever need to create barcodes on the fly, I have created a sort of API for them:

To create a UPC-A barcode, use the following pattern:

http://jazzychad.com/barcode/upca-<insert-12-digit-code-here>.png

Example:

http://jazzychad.com/barcode/upca-012000809965.png

will produce




To create a smaller version, simply add “small” after the 12-digit code, like so:

http://jazzychad.com/barcode/upca-012000809965small.png

will produce




If you would rather have a gif format rather than png, just use .gif instead.

UPC-E creation is very similar:

http://jazzychad.com/barcode/upce-<insert-6-digit-code-here>.png

Notice “upce” instead of “upca”.

Example:

http://jazzychad.com/barcode/upce-120850.png

will produce




Again, to create a smaller version, just add “small” after the 6-digit code:

http://jazzychad.com/barcode/upce-120850small.png

will produce




.png and .gif work the same way as well.

Note: UPC-A creation will still work even if the check-digit (the last digit after the barcode) is incorrect. I think I will change the script to indicate an invalid UPC-A code by turning the check-digit red.

I wanted to test scanning these barcodes after printing them out, but my CueCat seems to have died. Maybe I will take one to the store next time I want to buy a Mountain Dew 12-pack.

Resources:
Wikipedia UPC Article
Barcode Calculator Tool

Next Page →