Enhancing the urbarama mashup

In Urbarama mashup we looked at how to mashup mutiple APIS and serve up the result. Now we are going to use that to further enhance and publish the results. 

The problem with the Urbarama api is that it returns places of interest within a box of a given latitude/longitude. If we want instead to only return items within a given distance of the origin, we need to work with a circle radius instead, and discard anything that is in the box, but outside the circle.
urbarama mashup bounding box

In Delegation to Google Apps Script we have already created an urbenhanced script. Here's the code you need to paste in


function doGet(e) {
    return ContentService
            .createTextOutput(JSON.stringify (urbFilterCircle(e)))
            .setMimeType(ContentService.MimeType.JSON);     
}

function urbFilterCircle(e) {
  // the urbarama mashup returns all hits within a square, lets make that a circle
  var jSonResults = urbGetResults (e);
  // but we dont actually have the origin lat lon unfortunately so we'll need to ask it again 
  if (jSonResults) { 
    var results = JSON.parse(jSonResults);
    var geoCode = urbGeoRest(e.parameter.address) ;
    if (!geoCode.error) {
      var limit = e.parameter.limit ? e.parameter.limit : 20;
      var newProjects = [];
      // now we are going to trim the results of any places that are inside a square, but not a circle
      for ( var  i = results.projects.length -1 ; i > 0 ; i-- ) {
        // delete if outside range or we dont have a lat/lon
        if ( results.projects[i].hasOwnProperty("latitude")  ? 
                  (Math.abs( 
                    mcpher.getDistanceBetween(geoCode.lat,geoCode.lon,results.projects[i].latitude, results.projects[i].longitude)) <= limit)
                   : false
            ) newProjects.push (results.projects[i]);
      }
      // replace projects 
      results.originalTotal = results.total;
      results.total = newProjects.length;
      results.projects = newProjects;
    }
  }
  return results;
}
function urbGetResults(e) {
  var mashupUrl = 
    "https://script.google.com/a/macros/mcpher.com/s/AKfycbxsqeuAjem3sq35UH27XPn7nHRJdjw2HZ5t2Pv2GWzyFOJRNt4/exec";
  var results = {error : "no arguments specified"};
  if (e.parameter) {
   // make into url arguments
      var l = "?";
      var p = "";
      for ( var k in e.parameter ) {
        if (e.parameter[k]) {
          p += (l + k + "=" + e.parameter[k]);
          l = "&";
        }
      }
      var results =  new mcpher.cBrowser().httpGET (mashupUrl + p);
  }
  return results;
}
function urbGeoRest(address) {
  
  // this time we'll just use the rest library to geocode it

  var cr = mcpher.restQuery(undefined, "yahoo geocode", address, false,
                    undefined ,undefined , undefined, false, undefined, false) ;
  return cr ? 
    { address : address , 
        lat : mcpher.CDbl(cr.jObject().find("latitude").value()), 
        lon : mcpher.CDbl(cr.jObject().find("longitude").value()) 
    } : 
    { error: "couldnt geocode " + address} ;
}

function testUrb() {
  Logger.log ( urbFilterCircle (  { parameter : { address : "london" , within : 30 }} ));
}

What's happening here

Looking at the urbFilterCircle function,
  • urbGetResults executes the urbarama mashup as rest query, and gets the jSon results.
  • if that works, then we need to re geocode the address. It will already have been done in urbarama mashup, but it is not something that it returns. So we'll call the yahoo geocoder to do it again. Another alternative would have been to add this property to the original mashup, but I'm also using this example to illustrate the use of the rest library to do queries that already exist. urbGeoRest() simply asks the rest library, which is in the mcpher library, to do a geocoding. Note that all queries initiated by the mcpher library use the Google Cache service. This means that result of this query, previously done, will anyway be in cache.
  • if that worked, the we create a new array of qualifying addresses by comparing the distance between their co-ordinates and the origin, discarding those that are out of range.

Testing

TestUrb is provided to check the results before publishing. We can see from a query using London as the origin and a radius of 20km, that we discard 5 entries as being within the bounding box, but outside the radius.
{"total":100,"offset":0,"count":100,"projects":[ {"project_title":"Ravey Street Residence","project_url":"http://www.urbarama.com/project/ravey-street-residence", etc....
... }],"originalTotal":105}

Publishing

Now we are ready to publish the app, just as we did with Hosting your public scriptdb. My version of this is published at
https://script.google.com/a/macros/mcpher.com/s/AKfycbxvzTqn3fmW0SOdSOYqjwZh0itY066XhPb7YmHkDaztKOgX6Cqd/exec?entry=london&within=20
and is shown here with a couple of parameters.


For help and more information join our forum,follow the blog or follow me on twitter . Now take a look at the next step in step by step guide to delegating to Google Apps Script.

Comments