diff options
-rw-r--r-- | perllib/HighwaysEngland.pm | 36 | ||||
-rw-r--r-- | t/geocode/highwaysengland.t | 108 | ||||
-rw-r--r-- | t/geocode/roads.sqlite | bin | 0 -> 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 Binary files differnew file mode 100644 index 000000000..09cd0c9a7 --- /dev/null +++ b/t/geocode/roads.sqlite |