For a while I've been working quietly on a new project called "Rate This Spot". The basic idea is simple: Providing an instant way to rate all kinds of stuff based on its location. I think this is a powerful concept, in that it does not try to put ratings into little cubbyholes based on what it is you're rating. Instead, it relies on the human user to provide context and interpret the data to filter what is relevant to them at the time. The nice thing is: humans tend to be very good at doing exactly that.

There are two parts to the project: the interface the user interacts with, and a server backend that collects and serves the rating data. The first user interface I developed is a tiny app that runs on the Android platform (Also available in the Android Market). It is very basic right now: it has a satellite image map, a targeting crosshair that can be used to select the spot you want to rate, and three buttons: one each to express happy, neutral and unhappy opinions. The satellite image map is overlaid with a colored grid, indicating the aggregate ratings at a fairly coarse resolution.

To rate a spot, you just tap on the map to move the crosshair (or let the GPS do it for your current location), and push the button that represents your opinion. Done! I think it is important to make this process as easy as possible for the user, or hardly anyone will ever bother to do it. No need to select a different app based on what you're rating. No browsing through categories. You can see where you are on the map, visually aim for what you want to rate (like the building you're in), and just do it. Also, doing it right there and then makes the most sense as the opinion is still strong. As life goes on and the intensity and emotion of an experience fade away, few people would bother to go back to rate something later.

As mentioned before, the ratings are shown on the map as a pretty coarse grid of colors. The coarseness of the grid stays the same as you zoom in and out of the map. This is an important design choice. It means the system doesn't need to know the features of whatever is being rated to come up with aggregates that make sense, but the user can dynamically choose how specific he or she wants to see the ratings by changing the zoom level. For instance, to determine the rating of a small store on a strip mall, the user may want to zoom in so they get a rating for just the store they're interested in and not an average with the store next door. But maybe they want to decide if the mall is worth going to, and in that case, zooming out to a higher level will give them an aggregate rating for the whole mall. I think it will come quite naturally to match the size of the rating cells with whatever it is the user is trying to get a rating for in a way that makes sense to them.

On the technical side, this is the first Android app I ever wrote--it is actually the first Java program I ever wrote, and the whole experience went smoother than expected. I have plenty of experience with C and C++ and it turned out Java took very little time to get used to. Personally I still prefer the higher level programming of Python, and there was a little more housekeeping necessary than I liked, but Java may have been a good choice by Google in striking a balance between performance and ease of programming. Of course, the app is a simple one, since most of the functionality is provided by Google's awesome MapView control. I enjoyed the speed at which I was able to be productive.

On the server side, I implemented this on Google's AppEngine (GAE) for scalability. The great thing about GAE is that it promises a low threshold for small developers like me to play with things that might take on a massive scale. I know next to nothing about large scale server deployments, but with Google taking care of that, I really don't need to worry about it and can focus on my application instead. Of course, that is what Google marketing tells me. It will be interesting to see whether it pans out, if the app happens to become popular. Still, I likely wouldn't have started this project, if it hadn't been for this promise. It is easy enough to make something work on a small scale, but it sucks if you have to hope that it doesn't get big just because you have no clue how to deal with it then. With GAE being designed for large scale from the start, you at least can worry less.

The flip side is that because it is made to scale, Google's storage system is kind of a step back compared to features you get with a relational database. The problem I ran into is the fact that queries only support inequality comparisons on one property. Unfortunately, this makes straightforward two-dimensional latitude/longitude range queries impossible. There are ways around that using geohashing, but in trying different systems I found on the web, I concluded that they all consumed way too much CPU time.

CPU time seems to be the main bottleneck I had to contend with on GAE. I guess in some ways this is a good thing, because it forces you to come up with more efficient schemes and smarter ways to accomplish the same thing. I started with a system based on geomodel, but during my testing I ended up using so much CPU that I almost ran out of my 6.5 CPU hours free quota. That was just me testing, and I didn't want to know how much this would end up costing if people started using it! So I tried different ways and ended up with a system that during my testing never went above 0.01 CPU hours per day. At that point, I decided that this project was viable.

Another thing I found is that it pays off to make as little GAE API calls as possible. Try to do things in such a way that you can get multiple operations done at the same time. There is a lot of pre-processing and post-processing you can get away with in your own code before you will even start to come close to the CPU cost of making an extra API call. I tried to further optimize my code by adding memcache. But again, because of the high CPU usage in the API calls, and my application being more CPU limited than anything else, it didn't make sense to do it on the scale I intended. In the current implementation, memcache is still in use, but in a more limited fashion to take advantage of atomic operations for managing multiple ratings being added concurrently.

All in all, I'm thinking of this app mostly as an interesting experiment. I have invested some time, but hardly any money (just the $25 to sign up for the Android Market), so if it doesn't go anywhere, that's fine. It is great that opportunities like this now exist for little guys like me, and are not the exclusive field of big corporations anymore. I hope people will take to the app--I think there is a lot of potential in it. I want to see how people end up using it. I just released the app yesterday, and there is something very exciting about seeing ratings start to pop up all over the world. Like planting a seed and watching it grow. The difference is: everyone can watch it grow, and even help it grow! :)