aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perllib/HighwaysEngland.pm36
-rw-r--r--t/geocode/highwaysengland.t108
-rw-r--r--t/geocode/roads.sqlitebin0 -> 62464 bytes
3 files changed, 141 insertions, 3 deletions
diff --git a/perllib/HighwaysEngland.pm b/perllib/HighwaysEngland.pm
index dc5b494bb..1de0071d7 100644
--- a/perllib/HighwaysEngland.pm
+++ b/perllib/HighwaysEngland.pm
@@ -11,6 +11,8 @@ sub database_file { FixMyStreet->path_to('../data/roads.sqlite') }
my $junction = '(junction|junc|jct|j)\.?\s*(?<junction>.*?)';
my $road = '(?<road>[AM][0-9MT]*)';
+my $alt_road = '(?<altroad>[AMB][0-9MT]*)';
+my $services = '(?<services>[\w ]+services)';
my $space = '[\s,.]*';
sub junction_lookup {
@@ -19,10 +21,23 @@ sub junction_lookup {
|| $s =~ /^\s*$junction$space$road\s*$/i
) {
return _lookup_db($+{road}, 'junction', $+{junction}, 'name') || undef;
+ } elsif ($s =~ /^\s*$services\s*$/i
+ || $s =~ /^\s*$services$space$road\s*$/i
+ || $s =~ /^\s*$road$space$services\s*$/i
+ ) {
+ return _lookup_db($+{road} || 'ANY', 'junction', $+{services}, 'name') || undef;
} elsif ($s =~ /^\s*(?<road>[AM][^ ]*)$space(?<dist>[0-9.]+)\s*$/i
|| $s =~ /^\s*(?<dist>[0-9.]+)$space(?<road>[AM][^ ]*)\s*$/i
) {
return _lookup_db($+{road}, 'sign', $+{dist}, 'distance') || undef;
+ } elsif ($s =~ /^\s*$alt_road$space$road\s*$/i
+ || $s =~ /^\s*$road$space$alt_road\s*$/i
+ ) {
+ return _lookup_db($+{road}, 'junction', $+{altroad}, 'roads') || undef;
+ } elsif ($s =~ /^\s*$road$space(?<name>.+)\s*$/i
+ || $s =~ /^\s*(?<name>.+?)$space$road\s*$/i
+ ) {
+ return _lookup_db($+{road}, 'junction', $+{name}, 'guess') || undef;
}
}
@@ -30,9 +45,24 @@ sub _lookup_db {
my ($road, $table, $thing, $thing_name) = @_;
my $db = DBI->connect("dbi:SQLite:dbname=".database_file(), undef, undef) or return;
$thing = "J$thing" if $table eq 'junction' && $thing =~ /^[1-9]/;
- my $results = $db->selectall_arrayref(
- "SELECT * FROM $table where road=? and $thing_name=?",
- { Slice => {} }, uc $road, uc $thing);
+ my $results;
+ if ( $thing_name eq 'guess' ) {
+ $results = $db->selectall_arrayref(
+ "SELECT * FROM $table where road=? and name like ?",
+ { Slice => {} }, uc $road, '%' . uc $thing . '%');
+ } elsif ( $thing_name eq 'roads' ) {
+ $results = $db->selectall_arrayref(
+ "SELECT * FROM $table where (road=? and name like ?) OR (road=? and name like ?)",
+ { Slice => {} }, uc $road, '%' . uc $thing . '%', uc $thing, '%' . uc $road . '%');
+ } elsif ( $road eq 'ANY' ) {
+ $results = $db->selectall_arrayref(
+ "SELECT * FROM $table where $thing_name=?",
+ { Slice => {} }, uc $thing);
+ } else {
+ $results = $db->selectall_arrayref(
+ "SELECT * FROM $table where road=? and $thing_name=?",
+ { Slice => {} }, uc $road, uc $thing);
+ }
return unless $results;
if (@$results) {
my ($lat, $lon) = Utils::convert_en_to_latlon($results->[0]{easting}, $results->[0]{northing});
diff --git a/t/geocode/highwaysengland.t b/t/geocode/highwaysengland.t
new file mode 100644
index 000000000..7380a8437
--- /dev/null
+++ b/t/geocode/highwaysengland.t
@@ -0,0 +1,108 @@
+use FixMyStreet::Test;
+use HighwaysEngland;
+use Test::MockModule;
+
+my $he = Test::MockModule->new('HighwaysEngland');
+$he->mock('database_file', sub { FixMyStreet->path_to('t/geocode/roads.sqlite'); });
+
+
+for my $test (
+ {
+ search => 'M1, Jct 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction number second'
+ },
+ {
+ search => 'Jct 16, M1',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction number first'
+ },
+ {
+ search => 'M1 Jct 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'no comma as separator'
+ },
+ {
+ search => 'M1 Jct16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'no space in junction name'
+ },
+ {
+ search => 'M1 J16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'J for junction'
+ },
+ {
+ search => 'M1 Junction 16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'junction as word'
+ },
+ {
+ search => 'm1 j16',
+ latitude => 52.2302496115401,
+ long => -1.01582565724738,
+ desc => 'lower case search'
+ },
+ {
+ search => 'A1, B668',
+ latitude => 52.7323808633713,
+ long => -0.599568322474905,
+ desc => 'road with joining road second'
+ },
+ {
+ search => ' B668, A1',
+ latitude => 52.7323808633713,
+ long => -0.599568322474905,
+ desc => 'road with joining road first'
+ },
+ {
+ search => 'A1, A607',
+ latitude => 52.8975982569244,
+ long => -0.664016143160206,
+ desc => 'road with joining A road'
+ },
+ {
+ search => 'A1, Long Bennington',
+ latitude => 52.979716221406,
+ long => -0.746100037226323,
+ desc => 'road with junction town'
+ },
+ {
+ search => 'Long Bennington, A1',
+ latitude => 52.979716221406,
+ long => -0.746100037226323,
+ desc => 'road with junction town first'
+ },
+ {
+ search => 'A14, J2',
+ latitude => 52.3998144608558,
+ long => -0.916447519667833,
+ desc => 'road with more than one number'
+ },
+ {
+ search => 'Watford gap services',
+ latitude => 52.3068680406392,
+ long => -1.1219749609866,
+ desc => 'motorway services'
+ },
+ {
+ search => 'M1 42.1',
+ latitude => 51.7926609391213,
+ long => -0.411879446242646,
+ desc => 'road and distance'
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $r = HighwaysEngland::junction_lookup($test->{search});
+ is $r->{latitude}, $test->{latitude}, 'correct latitude';
+ is $r->{longtude}, $test->{longtude}, 'correct longtude';
+ };
+}
+
+done_testing;
diff --git a/t/geocode/roads.sqlite b/t/geocode/roads.sqlite
new file mode 100644
index 000000000..09cd0c9a7
--- /dev/null
+++ b/t/geocode/roads.sqlite
Binary files differ