Thursday, November 27, 2008

Geocoding with Google Spreadsheets (and Gadgets)

Update: Google is deprecating Google Spreadsheets gadgets, as they announced in this post, so I am no longer updating or supporting them. If you're a developer, you can try Apps Script or the Spreadsheets Data API to see if you can accomplish the same thing. If you're a user, sorry, sometimes Google shuts down little used features.

Recently, quite a few people pointed me out to Tony Hirst's post on "Data Scraping Wikipedia with Google Spreadsheets". This was a really cool post because it demonstrated alot of features about Google Spreadsheets that people don't take advantage of (but should, because they're awesome): importing data from webservices or websites, publishing spreadsheets, creating charts of data, etc. But, I was sad to see that Tony had to go through so much pain to just geocode the data. Most people I know wouldn't be able to create a Yahoo! Pipe to parse the CSV and geocode spreadsheet data.. there should be an easier way. Well, there is, and that's what this post will show.

Google Spreadsheets now lets people embed gadgets, just like they can on iGoogle, Orkut (OpenSocial), Google Maps (Mapplets), and other containers. Those gadgets can live within the spreadsheet, access un-published data from a worksheet, and manipulate that data into some useful or visual output. There are gadgets for creating timelines, motion charts, word clouds, and now, courtesy of me, a gadget for geocoding data. This is my secret weapon for geocoding small sets of data, and can hopefully help other people out there.

Here are the steps for geocoding a spreadsheet with the gadget:

  1. Create a new spreadsheet, and put the addresses into rows. If your address is composed of multiple columns, just concatenate those into one single column using the "&" operator. The image below shows a spreadsheet of Australian beaches:

  2. Click on the "Insert" menu and then select "Gadget...":

  3. This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in the URL to the gadget:

  4. The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select all the rows for the column with your address data, and you should see the Range text field update with the range. If it doesn't work, you can always manually type it in. After doing that, click the Apply button:

  5. Since I always hate having charts or gadgets cluttering my sheets (and I like taking advantage of screen real estate), I then usually select the "Move to own sheet" option from the gadget menu. If you don't opt to do that, atleast resize the gadget to give it a decent amount of space in the worksheet. (Image omitted because I accidentally wrote over it :).
  6. When the gadget loads, it will present instructions, a blank map area, and a "Find Addresses" button. Click the "Find Addresses" button. It will start sending geocoding calls using the Maps API, and filling in the sidebar and map with results. It will stop at 99 results, for both technical and legal reasons (just use the gadget multiple times if you have more data than that). Any addresses that failed to geocode will have a red marker and show up in the bottom left of the map. All the markers are draggable, so you can move them around to tweak the location (this was a really important feature to me- geocodes can often use a nudge or two). In this step, you may notice some of the data didn't geocode at all, and perhaps you'll go back to your spreadsheet, edit the address a bit, and do this step again. For example, I had to add "Australia" to some of the beaches in my spreadsheet for disambiguation with other beaches.

  7. When you're satisfied with the marker locations, then select all in the text field below the map, and copy the text. The text contains the latitude/longitudes in row-order for all the markers, and is formatted so that it's easy to paste into spreadsheet columns.

  8. Finally, create two empty columns in your worksheet, and paste that text into the cells. If you put your cursor in the first row/column, then it should paste perfectly and align with the address data.

  9. You're done! Now you can use the latitude/longitude data in your Google Maps API mashup, perhaps by using the Spreadsheets -> Map Wizard or the Spreadsheets Mapper.

For those of you intrigued by Google Spreadsheets Gadgets, you may also want to check out my Spreadsheets -> JSON/SQL/XML converter, Spreadsheets based Flashcards, and State-Based Cluster Map. And the code is open-source, so you might want to modify and improve them, too. :)

Saturday, November 15, 2008

BarCamp Sydney: Best way to start off a life in Sydney?

So, I just arrived in Sydney 4 days ago, on a fateful Tuesday morning. Since then, I've moved into an apartment with a fellow Googler), learned how to hang laundry out to dry, hung out with the Sys-Ops crew in the office until 3 am after getting kicked out of the Bungalow8 bar, and today, participated in BarCamp Sydney.

BarCamp Sydney started off with a debate about rolling your own CMS versus modifying a pre-existing one, which is really the eternal debate about rolling your own anything versus using pre-existing anythings, so it triggered a lot of discussion and a counter-session later. This was a good indication of the sessions to come: a technical topic with an opinionated audience.

Some of the most heated debates were during the HCI talk about user interfaces (I'm personally convinced that there's no such thing as one good universal interface - there's just a thing as a consistent experience and well trained users), and during the final discussion about CleanFeed, a proposed internet censorship ("filtering") system in Australia. And then, of course, a few of us engaged in the obligatory JQuery versus JavaScript debate in the hallway (fyi: JQuery lost).

The least technical session was also the one that went on the longest - "Mind Hacking." A professional stage hypnotist came to demonstrate how easily people can be suggested things via marketing and advertising, and she attempted to prove it through stage hypnosis. I desperately wanted to be hypnotized, with the hopes of obliviously quacking like a chicken on stage, so I was one of the 6 volunteers in chairs at the front of the room. Unfortunately, it appears that I'm too immature or rebellious to be hypnotized - every time I was meant to fall into a deep sleep, I ended up in a fit of giggles. It certainly didn't help when an enterprising man in the audience yelled "Take it off!"... ;)

I myself gave two different sessions during the day. The first was a code walkthrough of a simple App Engine app, showing off the various features of GAE (and I might have thrown in a few <blink> tags). You can download that code in a ZIP, or just read through it in the "Getting Started" documentation.

The second was a brief description of HTML5 with as many demos as I could fit in 20 minutes (just got through video and forms), and it was based on the talk I gave at FOSSmy last weekend. You can see the slides here, and download the demos here. Both talks seemed to go well, and I got a few compliments on presentation style after. As far as I've figured out, my presentation style is high energy plus demo plus explanation (= keep them awake, wow them, teach them).

After all the talks, we all enjoyed free drinks in a bar just for us, and then a bunch of us went to dinner at a nearby Italian place. There, I experienced the amazingness that is oysters+bacon and oyster+cheese. Omg, I never thought to put oysters plus melty cheese and white sauce together, but it is a cheesy seafood heaven in your mouth. We finished the meal by drawing naughty doodles on the tablemat and surrounding them with HTML tags (my use of <table> tags was finally justified).

I must admit; my motivations in attending BarCamp Sydney were twofold: 1) find an excuse to talk about Google/web technology, and 2) find some friends. Someone at the after-party actually told me (drunkenly) "I'd like to be your friend", and I replied honestly, "well, actually, I don't have any yet, so that'd be great". He was kinda taken aback, but hey, it's the truth. And I actually think maybe I did make a couple friends today, and I'm thrilled about that. I'm hoping that today will be a precursor to much fun + geeky times in Sydney, and I thank all of you who welcomed me here today :)

All pics here were taken by Halans, one of the unorganizers of the conference.

Monday, October 13, 2008

7 Things I Learnt about Japan

Here are some random things that I learnt about Japan from my first visit there last week. Keep in mind that most of my pre-knowledge before the trip was based on scenes from "Lost in Translation"... :)

  • More than just Sushi. I assumed that when I came to Japan, I'd spend my whole time eating Sushi, since I'm a huge fan of that here. But then I was brought out by various people who all insisted I try various types of Japanese fare - ramen in a cube (solitary food confinement), okiyanamaki (from Osaka- spelling completely off), tonkatsu (japanese chicken fingers, finger-licking good!), and even non-Japanese fare like Lebanese food.. and that's when I realized that there was so much deliciousness to be had in Tokyo if I'd give up my sushi obsession for the week. In retrospect, I never went out for any Sushi now I'll never know how it competes with the US equivalent. Oh well, next time!
  • Bowing, bowing everywhere. Japanese bow as a way of saying thanks or acknowledging you or something like that, so I was constantly surrounded by people bowing. Sometimes it was the hotel staff (there'd be 6 in a row bowing in the lobby - I felt like I was running through a gauntlet), sometimes it was developers saying goodbye. It was altogether awkward for me, since I wasn't sure whether I was supposed to bow back - I generally did a head nod, which I figure is like a mini bow, and better for my back anyway. The weird thing is that I'm now finding myself bowing in China ever so slightly.. which is completely unnecessary here. :)
  • 4 addressing modes. I'm not sure the linguistic term, but in Japanese, your speech changes depending on the level of you to your addressee - there's Honorary, polite, humble, and inferior. So if you're addressing the president, you'd use Honorary, and if addressing a customer, you'd use humble/inferior (to make the customer feel important). The modes change both suffixes of words and sometimes even the words themself (e.g. "eat" is different), and the more polite the mode, the longer the suffixes are. So that explains why it always felt like hotel clerks and cashiers were always saying so much to me, for so little of an occasion (like saying "thanks").
  • Half punk/half prep. In the offices and developer events, the Japanese people were often super dressed up, in business suits and the like. In walking the streets though, there were quite a few Japanese that were dressed in punk/goth/leather/lolita/etc. So it seems the norm is to be very formally dressed, and the "non-conformist" solution is to be very out there. Basically, nobody there does casual - the t-shirt & jeans scene just isn't their thing.
  • Japanese = Spanish? I found myself constantly thinking that I was actually listening to Spanish, as I was overhearing conversations or watching videos on MTV Japan. I figured out this is because they clearly pronounce all vowels in the Japanese language, as they do in Spanish, so their syllables are very similar. I also realized that I knew multiple Spanish developers in Japan (and only 1 Japanese developer)..which leads me to suspect that Spanish speakers are on to the similarities as well, and figured Japanese would be the next easiest non-Romance language to learn. The similarities actually tempt me to learn Japanese, since Spanish is one of those few languages I can actually pronounce, and I would like to learn an Asian language.
  • English.. not so much. In the world of restaurants and cafes, pretty much noone spoke or understood English and all communication was done through pointing and gestures (which worked). In the world of developers and engineers, there were some that could understand English, but many of them only understood Japanese (which is why my talk was translated simultaneously). However, even amongst those that could understand English, there were very few that could fluently speak English, and they were all clearly more comfortable speaking Japanese than English. I hadn't realized that English was such a low language on the Totem pole in Japan, and I now understand why the developer community there is so separate from our Europe/America community (with its own forums and Gurus) - they simply can't use our English resources. So, a big thanks to our localization team for getting a Japanese version of our documentation out this year!
  • Karaoke is awesome. Singing the opera part in "Bohemian Rhapsody" in a room of Japanese developers is something that everyone should experience. And of course, one always has to finish with "Living on a Prayer". I always believed it was a song embraced all over the world, and I have now proved it. Bon Jovi - you may kinda suck now - but you've done a great thing for world peace.

Tuesday, October 7, 2008

Using Notebook in a Delicious Way

Okay, I'll admit it. I was a big user of delicious during my first year in the "web2.0 world", despite the fact that it'd take 5 tries to type "" correctly. It was great to be able to bookmark stuff and then share my bookmarks with other people easily (e.g. "Check out all these visualization bookmarks I've collected").

But then I started working at Google, and resolved that I would try to use Google services for everything possibly - mostly because I hate multiple logins, and Google does seem to offer almost every service possible, so it seemed a reasonable goal. So when it came to bookmarks, I discovered Google bookmarks. Excited to find a replacement for delicious, I started using it 24/7. But then someone asked me for a suggestion of campus maps mashups, and I realized that there was no "publish" option for Google Bookmarks... and that was a very sad day indeed.

Now, as it happens, I happened to try out Google Notebook around that time - and realized that all my bookmarks were actually in an unfiled bookmark. I moved them over to a new notebook and published it here. So I'd accomplished the first goal - publishing my bookmarks - but now I wanted to be able to let people easily view certain tags in my bookmarks, and have permalinks for them. Unfortunately, the published notebook page had nothing like that - it's just a list, and I actually had to tell people "visit this page and CTRL+F for campusmap".

But, never fear - APIs to the rescue! Notebook has a read-only Google data API, which means that I can retrieve my notebook feeds in JavaScript just via the JSONP output (alt=json-in-script). So I used the API to create a gadget that lets users view all the labels in a notebook, and filter by the labels. I think the UI is pretty nifty - it shows all the labels in cloud-tag format (sized based on bookmark count), and then when you select a label, it will figure out which labels are still relevant for filtering by and grey out the rest. That makes it super easy to find which combination of labels are useful. Try it out below:

There are a couple of neat tricks to the gadget:

  • pagination: The Notebook API only gives 100 entries at a time - I wanted to be able to get all of my notes at once, so that I could show every category. So here's the code I used to get all the pages in the feed:
     function loadURL(url) {
        var script = document.createElement("script");
        script.src = url + "&callback=myCallbackFunction";
      function myCallbackFunction(root) {
        entries = entries.concat(root.feed.entry);
        var nextLink = findNextLink(;
        if (nextLink) { loadURL(nextLink);
        } else { createCategories(); }
      function findNextLink(links) {
        for (var i = 0; i < links.length; i++) {
          if (links[i].rel == "next") {
            return links[i].href;
        return null;
  • user preferences: I wanted to be able to permalink to certain labels, and I also wanted to be able to let other users use the gadget for their own feeds. So I used Gadget user preferences for the user ID and notebook ID (string type) and for the categories (list type). You can play with customizing the gadget here and you can see a permalink with the "campusmap" category user preference set here (notice the "up_categories=campusmap" in that URL). Here's what the UserPref for the labels looks like in the Module spec:
    <UserPref name="categories"
    And here's the code that toggles labels on if they're set in the preferences:
    var default_categories = prefs.getArray("categories");
        for (var i = 0; i < default_categories.length; i++) {

Note that you can actually extend this gadget for any Google data API feeds - you can test out feed URLs in this older version of the gadget. Youtube playlist feeds look kinda nifty in it - the tags are all over the damn place. Enjoy!

P.S. Notebook now has a bookmarklet, so it's easy to "note" any page in the browser directly into a published notebook. Whee!

Flex Tips (OR: Examples I Wish Had Been Easier to Find)

So, in the last several months of supporting our new Maps API for Flash and learning all about this new fangled thing called Flex, I've discovered some things:
1) OMG I love Flex and the fact that I can create a ColorSelector natively, and the fact that I can "bind" dynamic variables as data sources to UIComponents. I'm very close to deprecating my love for JavaScript.
2) There are alot of ways to use Flex components, and I often find that the way that I want to use a component is possible..but not example-ified enough.

So this post is just a collection of Flash API samples (shamefully copy and pasted from the demo gallery) that use Flex stuff in nifty ways. Hopefully I've now somehow helped future developers looking for examples. :)

Context Menu  This demo shows how to create a context menu on the map that gives the user an "Add Marker" option. When selected, a marker is created on the map at the clicked location.
Non-Map Classes used: ContextMenu, ContextMenuItem
View the source
Polygon with Effects & Filters  This demo shows a polygon with a DropShadowFilter applied, and a Glow effect applied to that polygon on mouseover. Any filter or effect can be applied to a polygon or polyline.
Non-Map Classes used: Glow, DropShadowFilter
View the source
TabNavigator InfoWindow  This demo shows how to use customContent to put a UIComponent (TavNavigator) inside an infowindow and create the effect of tabbed info windows.
Non-Map Classes Used: TabNavigator, VBox, UIComponent, TextArea
View the source
KML Parser  This demo uses the open source KML DOM parsing library from the utility library to parse a KML file and create a sidebar Tree list and corresponding map overlays.
Non-Map Classes Used: Tree
View the source
Store Locator  This demo lets the user enter an address, pick a radius, and then it queries a database through a PHP script, parses the resulting XML, and adds the resulting markers to the map and the store information to a sortable DataGrid.
Non-Map Classes Used: ComboBox, DataGrid, itemRenderer, DataGridColumn
View the source
Driving Directions with DataGrid  Lets the user enter to/from in a form and displays the steps in a customized DataGrid, and displays static maps in the info windows for each step.
Non-Map Classes Used: DataGrid, DataGridColumn, itemRenderer, ArrayCollection
View the source
PolygonOptions Playground  Lets you experiment with the properties of PolygonOptions (including the GradientStyle) and see the resulting Polygon placed on the map.
Non-Map Classes Used: Grid, GridRow, ColorPicker, ComboBox, HSlider
View the source

Tuesday, September 30, 2008

Going Dowwwwwwnnn... Under: See you Next Year!

So, as a random percentage of people out there in the world have discovered, I will soon be embarking on a voyage across the sea. It starts off with a trip to Tokyo, Japan, where I'll be participating in various Geo Developer events and chatting with folks in that office (and most importantly, learning how to be a Harajuku girl). I then travel to China, where I'll be spreading the Developer Relations love in the Shanghai and China offices and helping kick off our "Google DevFest" tour for external developers. The tour continues on to Singapore, Bangkok, Ho Chi Minh City, and Manila, and will cover developer tools like App Engine, Maps APIs (of course), OpenSocial, and a sprinkle of others. For more info, check out our uber-colorful landing page.

Technical Tangent: The landing page includes a logo designed by our latest Developer Relations Photoshop Master (and Earth API Expert), Roman Nurrik, and a map designed by me. The map is pretty simple, but has a couple neat tricks:

  • It loads data from a "geo-tagged" calendar feed. Each event embeds the lat/long in the "where" field like this:
    Bangkok @ 13.753846, 100.501757
    I choose this format both because it can be fed into the Google Maps search box, and it can be easily broken down into coordinates with a Regular Expression. Here's a snippet from my CalendarLayer class that gets the value of the where field from the calendar JSON feed, and turns it into a GLatLng:
        var location =$where[0].valueString;
        var pattern = new RegExp(/@\s*([\-0-9.]+)\s*,\s*([\-0-9.]+)\s*/);
        var matches = pattern.exec(location);
        if (matches != null) {
            var lat = parseFloat(matches[1]);
            var lng = parseFloat(matches[2]);
            var latlng = new GLatLng(lat, lng);
  • It produces a different random Google color upon mouseover of the sidebar elements, adding to the festive effect. I did this because there are only 4 Google colors, and 6 cities, and I didn't want to choose 2 of the colors to favor and duplicate (that's mean!). So I used our friend Math.rand():
       var colors = ["#ff0000", "#00ff00", "#0000ff", "#ffcc00"];
       var rand = Math.ceil(4*Math.random())-1;
       color = colors[rand];

Anyways, back to traveling. After the final DevFest, I'll be flying into Sydney, Australia, and staying there for 5 whole months. As some of you know, the Maps API team is entirely based in Sydney, so this means that I get to do Maps API support while actually sitting next to the team (which means constant nagging of the engineers about feature requests :). In addition, I'll be working on growing our developer outreach in Australia by helping to hire and train a permanently Aussie-homed Developer Advocate (apply here!), and possibly run some Google developer events down under, or just speak at other people's events. After 5 months, I'll return to America with a full Australian accent, and will deny any and all association with this country. :)

So, in conclusion: If you're from Asia/Southeast Asia, register and attend DevFest. If you're from Australia/New Zealand, email me about running/attending events or even just grabbing coffee (but not coffee, cuz I hate coffee, so croissants + hot cocoa, perhaps). If you're from America, try to keep this place in shape while I'm gone... or just give up and join me in Australia, I'll have a couch.

Cheers, Mates! I've got some learning to do.

Tuesday, September 23, 2008

Social Networks & Web2.0 Mapping Meetup: Abaqus, Planet9, FireEagle

Tonight I was once again the "Google Host" (=food+venue) for a meetup of the Web2.0 Mapping & Social Networks group. Catherine Burton organizes and runs the meetups, and adheres to a very strict but successful schedule:

  1. Everyone in the room introduces themselves, what they do, and answers a question of the night (tonight's was "if you had a buncha extra money, what would you do with it?"- i answered that i'd avoid filling out expense reports - others answered that they'd vote for obama :). There are actually a lot of people at these events (~80?) but as long as people are quick and snappy with their bios, it goes by quick and is a good way of knowing who'd be interesting to talk to later. The problem I see with a lot of developer events is that developers don't have an excuse to talk with eachother, and thus they don't. This way, I can say "So, you work on so&so?" and strike up a conversation. I know ice breakers are cliche and reminds folks of camp and school..but they work!
  2. Each of 3 presenters are given (something like) 10 minutes to present on their topic, and 5 minutes for questions. Catherine literally puts up colored placards to let them know that they're coming close to the end of their time, and she sticks to it. I admire that, as I've been put in that situation in the past and always found it awkward to try to slow presenters down and grab their attention while they're speaking. But she handles it in a non-obtrusive way. The small amount of time that they're given to present mean that they have to boil it down to the main points or demos that will be relevant for the mixed (tech/business/etc) audience. It also means they can hint at a lot of things that attendees will want to talk with them about later, individually or in small groups, so that also encourages future interaction.
  3. At the end of the meetup, freeform conversation is encouraged for 30 minutes to an hour, depending on how long the room is available (and how soon I have to kick people out). At the first meetup that I hosted, there was actually a group of people passionately involved in a conversation until midnight. This is the part of the night for attendees to meet eachother, ask additional questions of the presenters, discuss collaborations, etc. It's the part of the night where I've made a lot of good contacts: the guys from YourStreet, the guys from Eye-Fi, some startup folk, etc. Tonight I spent a few minutes pinging Tyler Bell's brain about FireEagle integration, and most of the time having everyone tell me that my 5months trip to Australia will be awesome. :)

The presenters tonight were Abaqus, Planet9, and FireEagle.

My quick take-aways from each of them were:

  • Abaqus: Cool way to upload GPS tracks, organizing those via tags, and sharing them on permalink pages or blog embeds. My favorite features were a nice marker-bounce-effect, and the ability to upload non-geotagged photos and have them geotagged to a track based on timestamp information in the photos + track. Oh yeah and they were using the Google Maps API, yay. :)
  • Planet9: I was really confused at first cuz I swapped Poly9 with Planet9 in my head (they both have spinny globes!), but once I figured out Planet9 was its own company, it was pretty cool. They're doing immersive worlds for navigation, entertainment, mobile, friend-finding, etc. They can even bring in dynamic ads to an environment based on location.
  • FireEagle: Well, everyone probably knows this, but FireEagle is Yahoo's service for tying together the various mechanisms (gps/cell tower/etc) for transmitting where-am-i data, storing them on a central account, and then providing a way for users to let other apps use that location data. It's a pretty cool idea, but for me, suffers from one main downfall: non-gmail login. I hate having so many damn logins and user profiles all over the web, and one of the reasons that I love Google is that I can log in once and have access to a gazillion apps. Anyway so the main solution to this problem would be either for Google to own everything, or for the internet to have a central user account system. But the short-term solution is for me to try to make an AppEngine app that lets me auth to FireEagle once and never again, and let me update my location data through that.

Anyway, it was good times once again. I encourage Bay Area folks to attend these meetups. And I need to stop saying "folks"..

Wednesday, May 7, 2008

Searching for faces with country domain restrictions with AJAX Image Search

Inspired by Phillip's nifty hack with Google Image search (People Around the World), I hacked together a gadget which uses the AJAX Search GimageSearch with the face restriction set and sending the appropriate search ("site:de" for German, e.g.). I also added a timer/randomizer for lazy people. Play with it below: Next step - Map it!

Saturday, April 12, 2008

Spelman College Gadgets Competition

A week after my Spring Break trip to Costa Rica, I flew down to Atlanta to help judge a college Gadgets contest. I crawled out of bed (before actually starting to sleep) for a 5am flight to Atlanta on the Friday, and arrived "12 hours" later at 5pm, just in time for the classic college pizza dinner. I chatted with Marcus Mitchell, who apparently is a rather high-up engineering director in NY, and then met Kevin Rabsatt, who used to work on Maps and is therefore cool with me. :)

Later that night, I held office hours for teams working on their Gadgets to meet with me to work out technical problems and get advice. Every consultation was different - some people were trying to figure out how to go from Dreamweaver to the Gadget editor (change relative URLs to absolute!), some were trying to figure out how to get around the cross-domain request (_IG_FetchContent!), and some were just looking for suggestions (e.g. add a tab with a Google code search, for the C++ cheat sheet gadget).

After that, the Googlers and I headed off to Sutra Lounge, where we started off with some drinks and then danced the rest of the night. The music was good (80s/hiphop/techno), and we even met some Atlanta Googlers there.

The next day, we woke up bright and early to judge the Gadgets competition. Each team presented their Gadget to us, explained the purpose, and showed off the functionality. I was really impressed with their presentation skills - that's something that usually CS students usually lack, honestly. The technical difficulty varied - but considering that the Gadgets contest was just one segment of the whole competition (and that they're full-time students) - I don't blame them for not having all the time in the world to spend on their gadgets. The breadth of the Gadgets was impressive - there were games, utilities, portals, and more. It was great when I could see the other students were sincerely interested in using another team's gadget for themselves. That, to me, is a definition of a successful Gadget. Check out pics from the competition below:

The rest of the day, Kevin and I tried to get work done in a lab while occasionally wandering out in the hall to watch the Lego Mindstorms robot competition. There's something fascinating about watching a robot - seeing it try to make its way around an obstacle course- wondering what it's "thinking" (or if it's simply been hard-coded).

At night, we checked out another club called Halo. It started off chill and I had my doubts as to its "club-ness", but the music and crowd picked up soon and we danced until the close @ 3am. We then went to a diner and wandered back into the hotel at 5am. I woke back up again at 8am, not feeling *terribly* amazing. Somehow I convinced myself to suck it up and go to the airport on time, but of course, the flight was delayed - delayed so much that I missed my connection in Dallas, TX. So, it took more than "12 hours" to get back to Palo Alto, but all in all, it was worth it. Atlanta was a fun city, and I need to go back to visit its Aquarium - I hear it's the biggest in the world now (better than Boston's??).

Wednesday, April 9, 2008

24 hours + 15 Google APIs + 45 students = ?

Last year, my colleague Jason and I were both just lowly college students at the University of Southern California. While there, we helped the UPE chapter organize a 24-hour programming contest, appropriately dubbed "P24". The contest comprised putting teams of students in our campus student center from noon-noon on the weekend, fueling them with all sorts of horrible junk food, pizza, and caffeine, and watching them hack desperately at their laptops into the wee hours of the night. Amazingly enough, the teams came up with some impressive and innovative projects (all to the tune of a "Tubes" theme).

So this year, we decided to try the contest again, but give it a twist and a new name: each project made during our "Google All-Nighter" would have to involve at least one of our numerous Google APIs. And since we didn't expect everyone to already be familiar with our APIs (apparently they're not yet taught in grade-school curricula), we spent the week before the contest holding workshops and talks about the APIs, alongside talks from UPE board members about general web development topics. Check out this page for links to all of our slides, codelabs, and even our ghetto attempt at taping the events (think "Blair Witch" style).

After a week of ingraining our APIs into the impressionable young minds of students, it was finally time for the All-Nighter to begin. 11 teams of students showed up to our campus building and made their nest for the night, surrounding themselves with Google-provided lava lamps and some going as far as making a multi-monitor setup and bringing a coffee machine (see pic).

We'd announced the theme of "Think Green" the night before, so most teams came prepared with project ideas involving the environment, thinking, or well, just the color green. They set up projects on, created design docs on the wiki (possibly spurred on by a 6pm contest for 'best wiki'), and began divvying up tasks amongst themselves (typically by designating a JavaScript lead, server-side lead, and graphics lead).

For us Googlers, the contest was just like extended coffee hours - teams would email or ping us on GTalk and ask for "maps help in side room" or "spreadsheets help needed by team geekc0ders" and we'd come running (or sluggishly crawling in the late hours) to their side. It was a great opportunity to see how novice users of our API were able (or unable) to use our documentation and APIs, and we now have a list of bug reports and feature requests from the students.

At the end of the 24 hours, I think we were all kind of anxious and wondering the same thing - would these teams of overworked students be able to come up with full apps using Google APIs in such a short period of time? As we watched them present their ideas and demos, the answer clearly became "yes." Judging was difficult, but we managed to award the following prizes:

  • Most Technical: "FaceMap" - An application that integrates the facebook API, google calendar, and google maps to help you see where your friends are and where they will be
  • Most Fun: "PigeonRanking" - A game where you play a pigeon that must shoot down enemy search engine carriers in order to find google search results.
  • Best use of Theme: "DreamBig" - A website with a Google map of endangered animals, aggregated environmentally thinking blog feeds, alarming statistics.
  • Best Overall: "ThinkMap" - A collaborative and interactive location-based internet games platform, built with the Google WebToolkit and using atleast 5 of our APIs.
  • Most useful - "Think Green with Your Cuisine" - A Maps API & LA CitySearch mashup that helps users find out both the price of a restaurant, and the CO2 waste that will result from visiting it.

All of the projects code is on our project hosting, tagged with uscgan2008, so feel free to check it out. Pics from the event are in this Picasa web album. Here's for hoping we get to hold another of these next year!

Friday, January 18, 2008

Using Google to Find Housing in SF

About a month ago, I decided that I wanted to find a new place. I'm currently living in a 1-bedroom apartment near the San Antonio Shopping Center in Mountain View, and I have a couple issues with it: 1) It's BIG. Until I moved my bed into it, the "bedroom" just served as an area for me to walk through on the way to the bathroom. It's entirely unnecessary for one person to have both a living room and a bedroom. (Keep in mind that I literally lived in a closet last year at USC). 2) I'm all alone, and 'fraid of the dark. I know, I'm supposed to get over that fear - but I can't help it if the monsters are still alive! It would be better for the environment for me to live with roommates, as there's a chance I'd then turn the lights off at some point, and it'd be better hygienically as there's a chance I'd take showers at night. 3) I miss having roommates. I love having the possibility of interaction with a human while I'm sitting on the couch coding and watching trashy TV.

So, thus begins the housing hunt. I started off at this AMAZING mashup site called CribQ (I knew about it as the author emailed me about geocoding issues previously). It's a Craigslist/Google Maps mashup similar to, but it takes it to a whole new level. It gives you a login, lets you rate listings, add notes, search by viewport and price range. Plus, it shows how Google Maps + Virtual Earth can live peacefully together: whenever you click on a marker, it loads the Birds Eye View for that location below the Google Map. How perfect is that? You get the great aerial navigation of Google Maps plus the hard-to-navigate-but-easy-to-look-at side view from Virtual Earth. Oh, and one more thing: it's a mashup of mashups. It has another tab that loads in a WalkScore ranking for that location, and WalkScore is another of my favorite Google Maps/AJAX Search mashups. So I used CribQ to find a listing from a guy interested in starting up a house in the Mountain View area, contacted him, and together we signed a lease for a house he'd found earlier using a different Google hack. He'd done Craigslist searches for certain housing criteria, then subscribed to them in Google Reader, and starred the ones he liked. The house he found was pimp - 4 bedrooms, outside covered hot tub, and plenty of room downstairs for a bar and dance floor. So thus began the hunt for a roommate, and of course, more Google hacks. We made a shared Google calendar between us for tracking when we were meeting up with potential roommates, created a Google doc for our ridiculously organized and comprehensive Craigslist roommates wanted listing, and created a Google spreadsheet to keep track of room rent prices/dimensions and potential roomie pro/cons. The collaborative aspect of Google technologies is what makes them so useful for doing something like a househunt together. Anyway, we're pretty much decided on our roommates now, and moving in in a few weeks. I look forward to using Google apps for doing our house party planning (and clean-up duties :)!