Implementing the bike-ride viewer
I recently bought an Android phone and my favorite app is called MyTracks which uses the phone's GPS to record where you've been. I mainly use it to keep a record of my cycling training rides. A similar app popular among cyclists is produced by Strava which integrates with their excellent website. However, their app did not seem to do a good job of acquiring and holding the GPS signal whereas I've had no problems with MyTracks. An added bonus of MyTracks is that it is all open source, giving me a chance to see the innards of a well-made Android app.
A nice feature of MyTracks is that when I finish a ride the data can be easily uploaded to a Google Spreadsheet and/or Fusion Table. I decided to try and write an app that would let a viewer of this site do a search to see where I'd been riding recently.
The goal:
Visitors to my site could select from a listbox how many days of track history to load.
All the relevant tracks would be loaded and displayed on a map.
The map could be interactive (panned/zoomed) and ride stats for each track could be seen (similar to the default maps created by MyTracks)
My data sources (updated by me after each ride):
A list of all tracks is stored in a Google Spreadsheet. This spreadsheet also contains summary statistics like ride duration, distance, and a link to a Google Map which displays the track.
Each track is stored in a Google Fusion table. These tables store the raw track data but none of the summary info.
I imagine there are many possible ways to achieve this. A few things I considered:
JavaScript - FusionTablesLayer on Google Maps.
Had the most examples in the API documentation and seemed most appropriate but I could not get the samples to work with Google Sites. There seem to be restrictions in using JavaScript on Google Sites, which is where I wanted to host the page.
For example, this site creates nice multi-layer maps and clean HTML, but it can’t be embedded in Sites:
A workaround seemed to be to embed a Custom Gadget to the site to wrap the JavaScript. This seems like the most flexible solution but I could not find an existing gadget that worked well and did not want to spend the time learning how to make my own. Also, the examples I did find did not display cleanly (the scripts were blocked by the browser for security reasons)
Each Fusion table provides a “Get embeddable link” option ( Maps > Visualize) that can be easily inserted (manually) into a Site (just edit HTML and paste). Using this didn't seem viable because:
Fusion Table API doesn't provide access to that code
I didn't want to redirect the visitor to another page (that I would dynamically generate which would contain the Fusion Table-provided maps. Some more discussion here.
Google Apps Script. This is the approach I finally took. I hadn't used (or really even been aware of) this service before. The concept reminds me of the MS Office VBA tools that I used years ago - it lets you automate your work by providing programmatic access to the application. This service provides an API to control many Google products, and the ones I am using are:
UI services to create the forms, respond to user events, display results
Maps services to generate a static map image
Spreadsheet services to query the spreadsheet data source
URLFetch services to query the fusion table data source
I also used the "experimental" Apps Script GUI Builder to create some UI elements. I hadn't donehttp://www.google.com/events/io/2011/sessions/enterprise-workflow-with-apps-script.html much Javascript programming so this was also an introduction to that language.
There are some problems with my implementation (mainly, it is slow - a ludicrous 20 seconds to load). And there are a few things that would have made my life easier:
I am querying both a spreadsheet and a fusion table because the spreadsheet provides summary info and the table provides a track. It would be nice if the fusion table contained everything I needed. Others agree with me.
I must examine each fusion table rather than query the API to return the tables of interest. Again, if MyTracks put all the data in a single table this might be solved.
The Google Apps Script documentation is quite poor. The videos and samples are very helpful.
When generating the paths on the static map I am running into the limit on allowable path length. I am currently decimating the input until it is below a threshold, but this creates problems, for example the map of my crit race on Sep 5 shows me cutting a lot of corners.
It took me too long to find this good Javascript reference. It also took me a while to find that CTRL-SHIFT-J in my chrome browser launches a Javascript interpreter which is very helpful in learning.
The online Google Apps Script editor is a real pain to work with. I'm used to my vi/emacs/eclipse keybindings, autocompletion, and general responsiveness - all of which this interface lacks.
I don't know the right way to develop in this environment and what I was doing couldn't possible be it. The save-reload page-examine spreadsheet log cycle got very tiresome. Some better testing functions would probably have helped a great deal. A way to dynamically play with the various APIs would also be very helpful.
TODO
Create some charts through Chart services API
Hopefully MyTracks will augment their Fusion Table output to alleviate some of my issues.