Skip to content

Instantly share code, notes, and snippets.

@chris48s
Last active September 13, 2017 13:40
Show Gist options
  • Save chris48s/3fc6b354dec4de6ae7d85b029f7ef5d1 to your computer and use it in GitHub Desktop.
Save chris48s/3fc6b354dec4de6ae7d85b029f7ef5d1 to your computer and use it in GitHub Desktop.

A bit of pseudo-code describing (at a very high level of abstraction) how an AddressBaseGeocoder() and a FuzzyGeocoder() (based on ONSPD) should behave and how we would interact with them.

g = AddressBaseGeocoder('SA8 4DA')
g.getLocalAuth() raises MultipleCodesException
g.getLocalAuth("10010020128") returns "W06000011"
g.getLocalAuth("100100624439") returns "W06000012"
g.getLocalAuth("spoons") raises NotFoundException

g = FuzzyGeocoder('SA8 4DA')
g.getLocalAuth() returns "W06000012"
g.getLocalAuth("100100624439") raises NotFoundException



g = AddressBaseGeocoder('SA1 3UT')
g.getLocalAuth() returns "W06000011"
g.getLocalAuth("100100357246") returns "W06000011"

g = FuzzyGeocoder('SA1 3UT')
g.getLocalAuth() returns "W06000011"
g.getLocalAuth("100100357246") raises NotFoundException
def geocode(postcode):

    try:
        g = AddressBaseGeocoder(postcode)
    except AddressBaseNotImportedException:
        g = FuzzyGeocoder(postcode)
    return g

.. this means that AddressBaseGeocoder() may generate an object where g.getLocalAuth() returns a value but g.getWard() throws an exception. That allows us to try + see if we get an unambiguous response + only address pick if the level of geography we care about requires it..

g = AddressBaseGeocoder('SA1 6HU')
g.getLocalAuth() returns "W06000011"
g.getWard() raises MultipleCodesException

if we just want local auth, postcode is good enough. If we want ward, we have to call g.getAddresses() and show an address picker so we can call g.getWard("100100360556") or whatever

@symroe
Copy link

symroe commented Sep 13, 2017

Maybe I'm thinking of out of scope cases here as Where doesn't currently do this, but if we wanted to use something like this in EE then we'd need to consider the following:

It's possible that a postcode could be split over some boundaries but not ones that we care about. For example, a police area will have a very low ratio of split postcodes compared to a polling district. We wouldn't want to offer an address picker if a postcode was split over two local authorities that are both in the same police area (or Westminster consistency or whatever).

Because of this we'd need to have a way of passing in the type of area we want like g.getAreas('constituency') and have that return or raise an exception or whatever.

So far so good (I think), but in the case of getting a list of elections, we don't know the types of areas we need to get until we know the elections that are happening in that area. Because of that we'd need some ability to say "get me the elections for this postcode, but check if any one of them needs an address picker". But then in other cases we might want to force it to offer an address picker for an area type that doesn't have an election, for example a polling district.

That makes the flow a little more complex, especially if it's over an API.

Anyway, random thoughts to complicate things more…

@chris48s
Copy link
Author

For example, a police area will have a very low ratio of split postcodes compared to a polling district. We wouldn't want to offer an address picker if a postcode was split over two local authorities that are both in the same police area (or Westminster consistency or whatever).

...

So far so good (I think)

Yep, so in that case you instantiate g = AddressBaseGeocoder('mypostcode'). g.getPoliceForce() returns "some result" and g.getConstituency() raises MultipleCodesException. If you want police forces, you don't need an address picker. If you want constituencies, you do. Happy days..

but in the case of getting a list of elections, we don't know the types of areas we need to get until we know the elections that are happening in that area

As for this case, I think it is sort of out-of-scope but also simultaneously raises valid questions about this approach (esp with reference to historic boundaries) and gets to the question of historic boundaries better than I was able to in our conversation.

My proposed implementation of the interface sketched out above is that a lookup by postcode or UPRN is backed by a query to either the ONSUD for AddressBaseGeocoder or ONSPD for FuzzyGeocoder. i.e: it is only using the current boundaries (or lookups - there are no 'boundaries' as such with this approach). That is fine if you want to get a code like W06000011 and say "give me all the elections that relate to this code". I think when I was writing this, that is what I had in mind, but as you've rightly pointed out that is not the model for Every Election. What we actually want is to do is get a grid ref and then say "give me all the elections relating to an area with a boundary that contains this grid ref (from any arbitary point in history)", and then use EE's boundary lookup, rather than codes supplied by either the ONSUD or ONSPD lookups. That is the correct model because the "from any arbitary point in history" aspect of that is useful and it also means that if we need to work with geographies that aren't in the ONSUD or ONSPD lookups (yet, or at all), we can.

However, I think what that means is that you either have to try and do what you've said and first work out all the boundaries that are a potential match for all of the UPRN grid refs described by a given postcode and then optionally show an address picker if any of the potential boundaries are split (which is going to be very inefficient), or you simplify it (computationally) and say: To do this properly™, a postcode is never enough for a query to EE: If we're always querying by point, we always need to give EE an accurate point because we have no way of knowing what level of accuracy is or is not acceptable before we've made the query. That means showing an address picker for every search on WhoCIVF. That massively reduces processing overhead but potentially creates other issues..

Oh god.. can open - worms everywhere!! I think that does change how I'm thinking about this but it is a good idea for that to happen now rather than after I've done loads of work on it..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment