WWW::MySociety::Gaze - An interface to MySociety.org's Gazetteer service


WWW-MySociety-Gaze documentation Contained in the WWW-MySociety-Gaze distribution.

Index


Code Index:

NAME

Top

WWW::MySociety::Gaze - An interface to MySociety.org's Gazetteer service

VERSION

Top

This document describes WWW::MySociety::Gaze version 0.02

SYNOPSIS

Top

    use WWW::MySociety::Gaze;

DESCRIPTION

Top

MySociety.org Gaze is a REST based gazetteer service. You can find out more about it here:

http://www.mysociety.org/2005/09/15/gaze-web-service/

WWW::MySociety::Gaze is a Perl wrapper around Gaze.

INTERFACE

Top

new

Create a new WWW::MySociety::Gaze.

get_country_from_ip( $ip )

Guess the country of location of a host from its dotted quad IP address. Returns an ISO country code or undef if the country code is unknown.

    my $gaze = WWW::MySociety::Gaze->new;
    my $country = $gaze->get_country_from_ip( '82.152.157.85' );

get_find_places_countries

Return the list of countries for which find_places has a gazetteer available.

Takes no arguments, returns a list of ISO country codes.

    my $gaze = WWW::MySociety::Gaze->new;
    my @countries = $gaze->get_find_places_countries;

find_places

Lookup a location in the gazetteer. Takes a number of key, value pairs as follows:

Parameters

country

ISO country code of country in which to search for places

state

State in which to search for places; presently this is only meaningful for country=US (United States), in which case it should be a conventional two-letter state code (AZ, CA, NY etc.); optional

query

Query term input by the user; must be at least two characters long

maxresults

Largest number of results to return, from 1 to 100 inclusive; optional; default 10

minscore

Minimum match score of returned results, from 1 to 100 inclusive; optional; default 0

Returns a list of hash references. Each hash has the following fields:

Name

Name of the place described by this row

In

Blank, or the name of an administrative region in which this place lies (for instance, a county)

Near

A reference to a (possibly empty) array of nearby placenames.

Latitude

WGS-84 latitude of place in decimal degrees, north-positive

Longitude

WGS-84 longitude of place in decimal degrees, east-positive

State

Blank, or containing state code for US

Score

Match score for this place, from 0 to 100 inclusive

get_population_density( $lat, $lon )

Given a latitude, longitude pair return an estimate of the population density at (lat, lon), in persons per square kilometer.

get_radius_containing_population

Return an estimate of the smallest radius around (lat, lon) containing at least number persons, or maximum, if that value is smaller. Takes key value parameters:

lat

WGS84 latitude, in decimal degrees

lon

WGS84 longitude, in decimal degrees

number

number of persons

maximum

largest radius returned, in kilometers; optional; default 150

get_country_bounding_coords

Get the bounding box of a country given its ISO country code. Returns a four element list containing max_lat, min_lat, max_lon, min_lon.

    my @bb = $gaze->get_country_bounding_coords( 'GB' );

get_places_near

Get a list of places near a specific location. Takes a list of name, value pairs like this:

lat

WGS84 latitude, in north-positive decimal degrees

lon

WGS84 longitude, in east-positive decimal degrees

distance

distance in kilometres

number

number of persons to calculate circle radius

maximum

maximum radius to return (default 150km)

country

ISO country code of country to limit results to (optional)

Returns a list of hash references like this:

Name

Name of the nearby place.

Distance

Distance from the base place.

Latitude

Latitude of the nearby place.

Longitude

Longitude of the nearby place.

Country

Country of the nearby place.

State

State of the nearby place (currently US only).

CONFIGURATION AND ENVIRONMENT

Top

WWW::MySociety::Gaze requires no configuration files or environment variables.

DEPENDENCIES

Top

None.

INCOMPATIBILITIES

Top

None reported.

BUGS AND LIMITATIONS

Top

No bugs have been reported.

Please report any bugs or feature requests to bug-www-mysociety-gaze@rt.cpan.org, or through the web interface at http://rt.cpan.org.

AUTHOR

Top

Andy Armstrong <andy@hexten.net>

LICENCE AND COPYRIGHT

Top


WWW-MySociety-Gaze documentation Contained in the WWW-MySociety-Gaze distribution.
package WWW::MySociety::Gaze;

use warnings;
use strict;
use Carp;
use LWP::UserAgent;
use HTML::Tiny;
use Text::CSV;

use constant SERVICE => 'http://gaze.mysociety.org/gaze-rest';

our $VERSION = '0.02';

sub new {
    my $class = shift;
    return bless {}, $class;
}

sub get_country_from_ip {
    my $self = shift;

    croak "Need an IP address"
      unless @_ == 1;

    my $ip = shift;
    croak "IP address must be a dotted quad"
      unless $ip =~ /^(?:\d{1,3}\.){3}\d{1,3}$/;

    my $answer = $self->_request( 'get_country_from_ip', ip => $ip );
    chomp $answer;
    return $answer eq '' ? undef : $answer;
}

sub get_find_places_countries {
    my $self = shift;
    return $self->_lines(
        $self->_request( 'get_find_places_countries' ) );
}

sub find_places {
    my $self = shift;
    croak "Need arguments as key, value pairs"
      unless @_ and ( @_ % 2 == 0 );
    return $self->_csv_to_hashes(
        $self->_request( 'find_places', @_ ),
        sub {
            my $rec = shift;
            $rec->{Near} = [ split /\s*,\s*/, $rec->{Near} ];
            return $rec;
        }
    );
}

sub get_population_density {
    my ( $self, $lat, $lon ) = @_;

    my @density = $self->_lines(
        $self->_request(
            'get_population_density',
            lat => $lat,
            lon => $lon
        )
    );

    return shift @density;
}

sub get_radius_containing_population {
    my $self = shift;
    croak "Need arguments as key, value pairs"
      unless @_ and ( @_ % 2 == 0 );

    my @radius = $self->_lines(
        $self->_request( 'get_population_density', @_ ) );

    return shift @radius;
}

sub get_country_bounding_coords {
    my ( $self, $country ) = @_;
    my @bb = $self->_lines(
        $self->_request(
            'get_country_bounding_coords', country => $country
        )
    );

    return split /\s+/, shift @bb;
}

sub get_places_near {
    my $self = shift;
    croak "Need arguments as key, value pairs"
      unless @_ and ( @_ % 2 == 0 );

    return $self->_csv_to_hashes(
        $self->_request( 'get_places_near', @_ ),
        sub {
            my $rec = shift;
            $rec->{Distance} ||= 0;
            return $rec;
        }
    );
}

sub _request {
    my $self = shift;
    croak
      "Need a verb and optionally a list of argument key value pairs"
      unless @_ >= 1 and @_ % 2;
    my ( $verb, %args ) = @_;
    my $ua = $self->{_ua} ||= LWP::UserAgent->new;
    my $uri = SERVICE . '?'
      . HTML::Tiny->new->query_encode( { %args, f => $verb } );
    my $resp = $ua->get( $uri );
    croak $resp->status_line if $resp->is_error;
    return $resp->content;
}

sub _lines {
    my ( $self, $text ) = @_;
    $text =~ s/\r//g;
    chomp $text;
    return split /\n/, $text;
}

sub _csv_to_hashes {
    my ( $self, $text, $cook ) = @_;
    my @lines = $self->_lines( $text );
    my $csv   = Text::CSV->new;

    my $csv_line = sub {
        return unless @lines;
        my $line   = shift @lines;
        my $status = $csv->parse( $line );
        croak "Can't parse $line: " . $csv->error_diag
          unless $status;
        return $csv->fields;
    };

    $cook ||= sub { shift };

    my @names = $csv_line->();
    my @data  = ();

    while ( my @fields = $csv_line->() ) {
        my %row;
        @row{@names} = @fields;
        push @data, $cook->( \%row );
    }

    return @data;
}

1;
__END__