Posts Tagged ‘hack’

Geo this! Geolocate Wordpress posts with Greasemonkey and Yahoo Placemaker

Monday, June 22nd, 2009

Geolocating content on the web is a great idea. By embedding latitude and longitude and real place names in your document you allow data mining for location or easy display on a map.

The problem up to now was that it is quite a job to find out the correct geo information from a text or a document and it is quite a pain to enter the information by hand.

Yahoo Placemaker is a web service that helps you with that – you give it some text or a document URL and it returns you all the things it found in there that resemble a geographical location back. The issue with doing that on a live site is that you slow down your site immensely as you need to look up every time.

The more logical place to do the lookup with Placemaker is when you edit your document. I thought this would be cool to have for this WordPress install here and wrote a small GreaseMonkey script that injects a new “Geo this!” button in the main WP form:

Geo this - button by  you.

When I hit the button the script does an Ajax request using the Placemaker open YQL table to get the information for the currently edited text.

Once it found the information it adds it at the end of the document as a GEO microformat. Each found entry starts with a comment that tells you what Placemaker matched and considered a geographical location. As it is not infallible this makes it easy for you to delete wrong entries.

Geo this - added microformats by  you.

Try it out yourself:

This is pretty much rough and ready and I’d be happy for feedback how to improve it.

Postcode from latitude and longitude or even IP – fun with Geo APIs and YQL

Tuesday, June 9th, 2009

One of the more complex things about GeoFill was to get postcode information from an IP. However with a collection of APIs and a collated YQL statement even this was possible.

The first thing I needed to get was the IP of the user. This is done with the GeoIP API based on the GeoLite API from MaxMind. This is available as an open table in YQL and can be used thus:

select * from ip.location where ip=""

Try the lookup in the console or check the lookup result

Response": {
  "Ip": "216.39.58.17",
  "Status": "OK",
  "CountryCode": "US",
  "CountryName": "United States",
  "RegionCode": "06",
  "RegionName": "California",
  "City": "Sunnyvale",
  "ZipPostalCode": "94089",
  "Latitude": "37.4249",
  "Longitude": "-122.007",
  "Gmtoffset": "-8.0",
  "Dstoffset": "-7.0"
}

This gives us a lot of information. What’s really important here is latitude and longitude, as this can be used in the flickr.places API to get a where on earth ID which is a much more defined identifier:

select * from flickr.places where (lat,lon) in (
  select Latitude,Longitude from ip.location where ip=""
)

Try the flickr places call in the console or check the flickr result

"places": {
  "accuracy": "16",
  "latitude": "37.4249",
  "longitude": "-122.007",
  "total": "1",
  "place": {
     "latitude": "37.371",
     "longitude": "-122.038",
     "name": "Sunnyvale, California, United States",
     "place_id": "P_ls_fybBJwdHP8t",
     "place_type": "locality",
     "place_type_id": "7",
     "place_url": "/United+States/California/Sunnyvale",
     "timezone": "America/Los_Angeles",
     "woeid": "2502265"
  }
}

Here the interesting part is the woeid which we can use to dig deeper into geo.places:

select * from geo.places where woeid in (
  select place.woeid from flickr.places where (lat,lon) in (
    select Latitude,Longitude from ip.location where ip=""
  )
)

Try the geo places call in the console or check the geo places result

The result is all the information you’d ever want.

"place": {
  "lang": "en-US",
  "xmlns": "http://where.yahooapis.com/v1/schema.rng",
  "yahoo": "http://www.yahooapis.com/v1/base.rng",
  "uri": "http://where.yahooapis.com/v1/place/28751237",
  "woeid": "28751237",
  "placeTypeName": {
    "code": "22",
    "content": "Suburb"
  },
  "name": "Fairgrounds",
  "country": {
    "code": "US",
    "type": "Country",
    "content": "United States"
  },
  "admin1": {
    "code": "US-CA",
    "type": "State",
    "content": "California"
  },
  "admin2": {
    "code": "",
    "type": "County",
    "content": "Santa Clara"
  },
  "admin3": null,
  "locality1": {
    "type": "Town",
    "content": "San Jose"
  },
  "locality2": {
    "type": "Suburb",
    "content": "Fairgrounds"
  },
  "postal": {
    "type": "Zip Code",
    "content": "95112"
  },
  "centroid": {
    "latitude": "37.326611",
    "longitude": "-121.878441"
  },
  "boundingBox": {
    "southWest": {
      "latitude": "37.275379",
      "longitude": "-121.89254"
    },
    "northEast": {
      "latitude": "37.330879",
      "longitude": "-121.808723"
    }
  }
}

Newsmap – using Placemaker to add geo location to a news feed

Friday, May 22nd, 2009

I am right now very excited about the new Placemaker beta – a location extraction web service released at Where2.0. Using Placemaker you can find all the geographical locations in a feed or a text or a web url and you get them back as an array of places.

As a demo I took the Yahoo News feed and ran it through Placemaker. The resulting places are plotted on a map and the map moves from location to location when you hover over the news items.

The result is online at http://isithackday.com/hacks/placemaker/map.php

Yahoo News Map by  you.

Getting the data from the data feed and running it through placemaker is very straight forward. I explained the basic principle in this blog post on the Yahoo Developer Network blog. The only thing to think about is to define the input and output types correctly:


<?php 
$key = 'PASTE YOUR API KEY HERE';
$apiendpoint = 'http://wherein.yahooapis.com/v1/document';
$url = 'http://rss.news.yahoo.com/rss/topstories';
$inputType = 'text/rss';
$outputType = 'rss';
$post = 'appid='.$key.'&documentURL='.$url.
                '&documentType='.$inputType.'&outputType='.$outputType;
$ch = curl_init($apiendpoint);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
$results = curl_exec($ch);
?>

If you look at the source of this example you will find that Placemaker injected contentlocation elements in the feed itself:


<cl:contentlocation 
xmlns:georss="http://www.georss.org/georss" xmlns:cl="http://wherein.yahooapis.com/v1/cle"
xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:lang="en">
  <cl:place>
    <cl:woeId>2514815</cl:woeId>
    <cl:name><![CDATA[Washington, DC, US]]></cl:name>
    <cl:latitude>38.8913</cl:latitude>
    <cl:longitude>-77.0337</cl:longitude>
  </cl:place>
  <cl:place>
    <cl:woeId>23424793</cl:woeId>
    <cl:name><![CDATA[Cuba]]></cl:name>
    <cl:latitude>21.511</cl:latitude>
    <cl:longitude>-77.8068</cl:longitude>
  </cl:place>
  <cl:place>
    <cl:woeId>23424977</cl:woeId>
    <cl:name><![CDATA[United States]]></cl:name>
    <cl:latitude>48.8907</cl:latitude>
    <cl:longitude>-116.982</cl:longitude>
  </cl:place>
  <cl:place>
    <cl:woeId>55843872</cl:woeId>
    <cl:name><![CDATA[Guantanamo Bay, Caimanera, 
    Guantanamo, CU]]></cl:name>
    <cl:latitude>19.9445</cl:latitude>
    <cl:longitude>-75.1541</cl:longitude>
  </cl:place>
</cl:contentlocation>

You’ll also notice that the elements are namespaced and the names of the locations in CDATA blocks, both things I hate with a passion. Not because they don’t make sense, but because simplexml can be drag to make understand them.

What I wanted to do with this data was twofold: create a JSON array of geo locations to plot on a map and a display of the news content. This is the PHP that does that:


$places = simplexml_load_string($results, 'SimpleXMLElement', 
                                LIBXML_NOCDATA);  
// if there are elements found
if($places->channel->item){
  // start a JSON array
  $output .= '[';
  // start the HTML output
  $html = '<ul id="news">';
  // set the counter - this will be needed to link news 
  // items and map markers
  $count = 0;
  // loop over RSS items
  foreach($places->channel->item as $p){
    // set inner counter (as there are more locations per news item)
    $innercount = 0;
    // start the HTML list item and give it an ID with the counter
    // value
    $html .=  '<li id="news'.$count.'"';
    // all child elements with the defined namespace
    $locs = $p->children('http://wherein.yahooapis.com/v1/cle');
    // check that there is a location sub-element in this item
    if($locs->contentlocation){
      // if there is one, add a class to the LI
      $html .= ' class="haslocation"';
      // start an array for displaying of the locations under the
      // news items
      $dlocs = array();
      // loop over all the places found for this item
      foreach($locs->contentlocation->place as $pl){
        // append a new JS object with the location data
        // and a unique ID to the locations array 
        $locations[] = '{"name":"'.$pl->name.'","title":"'.
                        preg_replace('/\n+/','',addslashes($p->title)).
                       '","lat":"'.$pl->latitude.
                       '","lon":"'.$pl->longitude.'","id":"m'.
                       $count.'x'.$innercount.'"}';
        // add the location name to the display locations array
        $dlocs[] = $pl->name;                
        // increase the inner count to ensure that every marker has 
        // a unique ID
        $innercount++;
      }
    }
    // append the HTML for the news item
    $html.='><h2><a href="'.$p->link.'">'.$p->title.'</a></h2><p>'.
            $p->description.'</p>';
    // if locations were found, add them 
    if(sizeof($dlocs)>0){
      $html.='<p class="locations">Locations: '.join(',',$dlocs).'</p>';
    }
    // end the list item
    $html.='</li>';
    // increase the counter
    $count++;
  }
  // join the json object data with a comma and close the JSON array
  $output .= join(',',$locations);
  $output .= ']';
// if there are no items simply return nothing
} else {
  $output = '';
}
// and this ends the HTML
$html.= '</ul>';
?>

The result of this can be seen here http://isithackday.com/hacks/placemaker/map-2.php.

The JavaScript to show the map is pretty straight forward and more or less the demo example of the maps API:


// will be called with the array assembled in PHP
function placeonmap(o){
  // if there are locations
  if(o.length > 0){
    // create a new geopoints array to hold all locations
    // this is needed to determine the original zoom 
    // level of the map
    var geopoints = [];
    // add map with controls
    var map = new YMap(document.getElementById('map')); 
    map.addZoomLong();
    map.addPanControl();
    // loop over locations
    for(var i=0;i<o.length;i++){
      // define a new geopoint and store it in the array
      var point = new YGeoPoint(o[i].lat,o[i].lon);
      geopoints.push(point);
      // create a new marker and give it the unique
      // id defined in the PHP. Pop up the title of 
      // the news item and the name of the location when the
      // user hovers over the marker
      var newMarker = new YMarker(point,o[i].id);
      newMarker.addAutoExpand(o[i].title + '('+o[i].name+')');
      map.addOverlay(newMarker);
    }
    // define best zoom level and show map
    var zac = map.getBestZoomAndCenter(geopoints);        
    map.drawZoomAndCenter(zac.YGeoPoint,zac.zoomLevel);
  }
  // add a mouseover handler to the list of results
  YAHOO.util.Event.on('news','mouseover',function(e){
    // remove the "news" text of the ID of the current target
    // as we named the list items news0 to news19
    var id = YAHOO.util.Event.getTarget(e).id.replace('news','');
    // if there is still something left we have one of the news
    // items
    if(id!==''){
      // get the first marker with the ID we defined in the loop.
      var marker = map.getMarkerObject('m'+id+'x0');
      // if there is one, pan the map there and show the message
      // attached to it.
      if(marker){
        map.panToLatLon(marker.YGeoPoint);
        marker.openAutoExpand();
      }
    }
  });
}
// call placeonmap with the JSON array
placeonmap(<?php echo $output;?>);

That’s pretty much it. I am sure it can be refined, but it is amazing how easy it is to get geo information into any text with Placemaker.

TTMMHTM: Sorry Jinho answers, twittering cat flaps, hot goths and the real AYB

Monday, May 18th, 2009

Things that made me happy this morning:

Pitching a hack (or a product) do’s and dont’s

Saturday, May 16th, 2009

Disclaimer: Dearie me, some of this is very subjective and may completely disagree with what worked for you. This is great and please leave a comment about what worked and what tips you can give rather than shooting one of the points here down in flames. I simply listed what I was looking for and what worked well for me in the past.

We just came back from the University hack day in Sunderland, England where students pitched hacks they built in a few weeks to judges that were meant as mock clients. As students asked us for feedback on what went well in the presentations and what didn’t here are some tips and tricks.

Pitches are not sex – you don’t need foreplay

The first mistake almost every group made was to introduce who they are and what they used to make the hack. This was partly a requirement of the assessment but it is also a sure-fire way to bore judges or VCs. There are two ways you can go:

  • Show your hack and what it does and then go into the details or
  • Explain the one problem that your hack solves and show the hack immediately afterwards as the solution.

Either approach has to answer some questions right off the bat:

  • What does the hack do?
  • Why should I use it?
  • Who is it for?
  • What does it do better/different than other solutions?

On being a team

The hack teams were 6-7 people each. Introducing each and every one of them costs a lot of precious time that you cannot use to make the audience interested in your product. Introduce only the needed people – those who will give the pitch and tell after the presentation who else did what in case there are specialist questions that need answering.

Anybody who is not part of the immediate pitch should not be standing around – all they do is distract from the presentation. Absolute suicide is to have people standing on the side scratching various body parts or looking at the ceiling or out of the window. If you pitch as a team, everybody should be awake and damn excited about the product – else you’re doing a better job sitting on the bench.

Your main spokesperson should be the most excited about the product. There were a few presentation wheres the first pitcher was amazing and had us going and when handing over to the tech guy to explain the product snoozing kicked in. If you hand over from presenter to presenter keep the energy flowing, otherwise don’t hand over.

If you have different experts delivering different parts of the pitch have them introduce each other and have their expertise be a natural part of the flow of the presentation. Some teams did a great job at that, with simple sentences like “in the future this will be extended to become important for more audiences and my colleague XY will show you what we have planned on the business side of things.”

On running your presentation

You are the presenter which means that you define the pace of the presentation and which slides are shown. You cannot have somebody else as your slide-jockey – it is terribly unprofessional to have to tell somebody to change the slide or even worse go back some slides. Presenter remotes are not expensive and most places will have some for installed equipment so use these instead. Your focus as the presenter is on the audience or jury and eye-contact is terribly important.

This applies to longer presentations, too. You can find out a lot from the audience reactions. When I present to a big crowd, one trick is to pick out a new single person in the audience I talk directly to every few slides. This is especially good to do if you pick people that seem to drift away and ask yourself what is the “what is in it for me” for that person.

Slides are an aid – not your pitch

One of the rookie mistakes is to have slides that tell and spell out everything you want to say. Less is more – much more. One word could be enough if it is backed up by your presentation. You can and should have a handout that explains details but this should not be your slide deck. Screenshots are good in case the wireless forsakes you – which it always does. Random clipart is bad as the 80ies are definitely over. Humour works – I loved for example typical English self-deprecation when one of the presentations introduced students as a target audience with a student wearing a traffic-cone hat as the example photo.

See your slides as the table of contents of your presentation – not the transcript and definitely not a different story. When your talk deviates from what is written on the wall you’ve lost us.

Bullet points are effective but also have become almost a cliche for presentations. If you feel comfortable with them, by all means use them but never have more than 3-5 on a slide with one short sentence for each.

You learn presentation writing by looking at successful presentation decks. A great resource is SlideShare where people upload their decks and the comments and views show you which ones are successful. My own slides there are all licensed with Creative Commons, which means that I am happy for you to re-use them.

Basic, really very basic typography

This applies to both the slides and the product itself. Legibility and professional type layout is very important. This is not because we are anal about this (and believe me there are a lot of people on the web that are) but there is a subconscious unease when we read things as humans and get lost because there is something not right with it.

Comic Sans Serif was lately added to the Geneva convention as a forbidden weapon when dealing with audiences that are above 3 years of age or don’t suffer from learning disabilities (this is not an evil jib – Comic Sans really proved to be very effective for these groups). Other than that pick a friendly, easy to read font that shows you mean business.

Bullet points should never be center aligned on the screen, unless they are a centered block.

Basic Bullet point etiquette

Use a large enough font size and good contrast of background and foreground to keep your slides and products readable even on a terrible projector. Don’t rely on colours to be shown the way you expect them to be.

On web applications, nothing spells “we are unprofessional” more than not defining a font for your text. Out of the box browsers render in Times New Roman, so you just look sloppy if you don’t change that.

If you have no clue about HTML and CSS and you don’t want to bother with it but show something that is readable and works across all browsers, use the YUI grids in your document:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  <title>My awesome App</title>
  <link rel="stylesheet" href="http://yui.yahooapis.com/2.7.0/build/reset-fonts-grids/reset-fonts-grids.css" type="text/css">
  <link rel="stylesheet" href="http://yui.yahooapis.com/2.7.0/build/base/base.css" type="text/css">
</head>
<body>
<div id="doc" class="yui-t7">
  <div id="hd" role="banner"><h1>My awesome App</h1></div>
  <div id="bd" role="main">
    <p>I rock! I really do</p>
  </div>
  <div id="ft" role="contentinfo"><p>&copy; by me, thievses!</p></div>
</div>
</body>
</html>

This adds a very basic level of typography for free and with the CSS hosted (and, if needed, fixed) by Yahoo for you.

Explain the unique – not the very obvious

What you want to achieve with a pitch is to get us excited and interested about what you did. The only real way to do that is to tell us what your system does differently than others – “what is it that makes it unique?” is the question you need to answer.

Get the one thing that makes your product great and shine the world’s biggest light on it.

Do not tell us that you have a delete, update and edit button. Do under no circumstances show us what happens when you click the delete button and – oh wonder of wonders – it deletes something. Then please do not continue to tell and show us the other – as predictable – functionality. Do tell us when one of these functionalities deviate from the normal patterns and do a better job though.

Do not tell us what colours you used in the background, we can see that and the colour is a means to an end, not the main reason to build the hack. Time is precious, do not waste it on things that we can find out for ourselves.

Cover the big concerns

Two things drive people nuts on the web: lacking security and hard to use products. If you ask for data show that you protect that data (some teams did a great job doing that, thanks). If you claim your interface is easy to use, don’t get lost trying to show it and under no circumstance tell other people who show the product for you what to do. “No, click the other button, no the other above this one” does not spell “millions of users will have a great time using this”.

People get annoyed very quickly if things take too long on the web. We use computers and online systems to make our lives easier, not to wait for your system or go through a five step process that could be one. Some teams did a great job with this. Sentences like “you don’t need to sign up, only when you want extra functionality explained here” are a real winner!

Tell the human story

What you build is there for humans. It is great if it makes their lives easier, it is good when it allows them to learn something and it is even OK when it just amuses them for a short while. Don’t get stuck with the technology but find the human aspect of your product instead.

Tell the story of the mother who hasn’t got enough time to juggle the day to day caring for her kids and the hard to use school enrollment and booking system. Tell the story that you got lost and tried hard to find the nearest bus stop and would have loved to get your mobile out and find it. Tell the story that you were not able to enjoy a party as you had no clue when the last train ran so you couldn’t relax as you didn’t want to get marooned there.

Computers are bastards

Things will go wrong in your presentation and you should swiftly deal with that and move on. Most presenters did that. Immediately say what happens normally and move on to the next integral part that works. Even better is when your product shows a great, well worded and easy to understand error message. Failure is as normal as success in software – both cases need a good user interface and not leave the user puzzled what is going on.

Do not try to gloss over

If you get caught out not having thought of something – own up and thank people for the great suggestions. Do not try to skirt around the issue and say that this is in there but you can’t show it now or something like that. Do not make something look as if it is more than it is – with web products it is far too easy to catch you out. Explain why things got omitted and there is no problem with that.

Don’t pad, build one thing well and sell this one

One thing that goes down terribly bad is adding gadgets gizmos and features to make a product look cooler. If a map display does not really aid the main task you try to make people achieve – don’t add it. News show that the site is up to date but can also distract from the real reason the site is there. Photos are fun but are they really needed for a time table application? Don’t think about what can be added but what can be removed. If you can’t remove any more and still make it easy to do what people come for to do you have a winner.

In summary

These are the main problems we found. Overall we had a great time and we were very impressed with both the presentations and the products. I remembered my own school time and I know how scared the presenters must have been. In that regard I have to say great job, guys.

Wait till I come! is the blog of Christian Heilmann , a developer evangelist living and working in London, England. Download vcard.

Feed me, Seymour: Entries (RSS) and Comments (RSS).