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.
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.
Now take a look at the next step in step by step guide to delegating to Google Apps Script.