Sunday, April 11, 2010

Building a random postcode generator

Some time a go I noticed that the keywords ‘random postcode generator’ were landing quite a few people at my website, even though I didn’t have a random postcode generator. Which got me thinking there must be a need for such a tool, if people were ending up at a site that didn’t have one desperately looking for it. So I built one and it’s now the most visited page on my site.

So that’s my little success story. But then I started wondering why anybody would want a random postcode anyway. I guess some people are just after a fake postcode they can plug into a website registration form, for whatever reason, and that page will do the trick nicely. But I imagine there are other people who need to generate random postcodes programmatically for some reason, so I’m going to explain how my postcode generator works. It may not be the best approach, but it seems to work.

I guess one approach would be to have a complete list of UK postcodes and just select one at random. I didn’t have a complete list of postcodes and you probably won’t either, unless you’ve bought the PAF database from the Royal Mail. So I went for a more long winded approach that requires less initial data to get working. First I got together a table of postcode districts (original list and my more programmer friendly version), which is the first half of a postcode. Potentially you could try to create this part of the postcode randomly but you’d end up creating invalid postcodes a lot of the time. Also, not all postcode districts are of the same format.

So with this table in place, I get a random postcode district and then append a random second half of the postcode (which is always of the form digit-letter-letter). I did this in PHP using the following (this contains some code which is specific to my website but you should be able to modify for your own needs)

  $result = DbQuery("SELECT Postcode FROM PostcodeDistricts ORDER BY rand( ) LIMIT 1");
  $line = mysql_fetch_array($result, MYSQL_ASSOC);
  $num = rand(0,9);
  $firstChar = rand(1, 26);
  $secondChar = rand(1, 26);
  print($line["Postcode"] . " " . $num . chr(64+$firstChar) . chr(64+$secondChar));
  mysql_free_result($result);

The only problem with this is that it will sometimes generate invalid postcodes, so the next step is to check the postcode is valid. I did this using Google’s Local Search API from JavaScript, as so.

  <script type="text/javascript">
    /* <![CDATA[ */
    function CreateRandomPostcode()
    {
      document.getElementById("postcode").innerHTML = "Thinking";
      TryCreateRandomPostcode();
    }
 
    function TryCreateRandomPostcode()
    {
      document.getElementById("postcode").innerHTML += ".";
      var xmlhttp;
      if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();     // Firefox, Safari, ...
      }
      else if (window.ActiveXObject)   // ActiveX version
      {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");  // Internet Explorer
      }
 
      xmlhttp.onreadystatechange = function() {
        if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
          Geocode(xmlhttp.responseText);
        }
      }
      xmlhttp.open("GET", "CreateRandomPostcode.php", true);
      xmlhttp.send();
    }
 
    function Geocode(postcode)
    {
      var localSearch = new GlocalSearch();
      localSearch.setSearchCompleteCallback(null,
        function()
        {
          if (localSearch.results[0])
          {
            var results = localSearch.results[0];
 
            if ((results.lat > 49) && (results.lat < 61) && (results.lng > -12) && (results.lng < 3)) {
              document.getElementById("postcode").innerHTML = "Your random postcode is " + postcode;
              document.getElementById("lat").value = results.lat;
              document.getElementById("long").value = results.lng;
            }
            else {
              TryCreateRandomPostcode();
            }
          }
          else
          {
            TryCreateRandomPostcode();
          }
        });
 
      localSearch.execute(postcode + ", UK");
    }
 
    /* ]]> */
  </script>

Basically it tries to geocode the postcode and if it fails (or it lies outside the UK), assumes the postcode is not valid and tries a different postcode until a valid one is produced. This could all be done server-side by hacking the Local Search API, but this met my simple needs.

4 comments:

paulc said...

of course, the OS CodePoint product is now available through the Open Data initiative: http://www.ordnancesurvey.co.uk/opendata/

Doogal Bell said...

Good point, I didn't realise OS Open Data included postcode data

John Pickard said...

Hi! Where do you get the STD codes from for the phone number portion of your generation code.

Regards,

John

Chris Bell said...

From here
https://www.doogal.co.uk/UKPhoneCodes.php
I think the original data was from Wikipedia