From 429eb4ad5ff3e931b244efe8b4b630594f4d54a5 Mon Sep 17 00:00:00 2001
From: ImBenji <53883070+YesItsBenji@users.noreply.github.com>
Date: Sat, 2 Mar 2024 18:07:05 +0000
Subject: [PATCH] near final
---
android/app/src/main/AndroidManifest.xml | 3 +
assets/datasets/bus-blinds.csv | 5164 +++++++++++++++++
lib/audio_cache.dart | 35 +-
lib/auth/api_constants.dart | 1 +
lib/backend/live_information.dart | 179 +
lib/backend/modules/announcement.dart | 330 ++
lib/backend/modules/commands.dart | 224 +
lib/backend/modules/info_module.dart | 8 +
lib/backend/modules/synced_time.dart | 36 +
lib/backend/modules/tracker.dart | 199 +
lib/main.dart | 25 +-
lib/pages/components/ibus_display.dart | 70 +-
lib/pages/display.dart | 35 +-
lib/pages/home.dart | 658 ++-
lib/pages/routes.dart | 213 +-
lib/pages/settings.dart | 202 +-
lib/pages/tfl_dataset_test.dart | 491 +-
lib/singletons/live_information.dart | 855 ---
lib/tfl_datasets.dart | 183 +-
lib/utils/OrdinanceSurveyUtils.dart | 35 +
lib/utils/audio wrapper.dart | 96 +-
lib/utils/delegates.dart | 18 +-
linux/flutter/generated_plugin_registrant.cc | 8 +
linux/flutter/generated_plugins.cmake | 2 +
macos/Flutter/GeneratedPluginRegistrant.swift | 6 +
pubspec.lock | 116 +-
pubspec.yaml | 7 +
.../flutter/generated_plugin_registrant.cc | 12 +
windows/flutter/generated_plugins.cmake | 4 +
29 files changed, 7870 insertions(+), 1345 deletions(-)
create mode 100644 assets/datasets/bus-blinds.csv
create mode 100644 lib/backend/live_information.dart
create mode 100644 lib/backend/modules/announcement.dart
create mode 100644 lib/backend/modules/commands.dart
create mode 100644 lib/backend/modules/info_module.dart
create mode 100644 lib/backend/modules/synced_time.dart
create mode 100644 lib/backend/modules/tracker.dart
delete mode 100644 lib/singletons/live_information.dart
create mode 100644 lib/utils/OrdinanceSurveyUtils.dart
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index cd438d5..90fc3f8 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -33,4 +33,7 @@
android:name="flutterEmbedding"
android:value="2" />
+
+
+
diff --git a/assets/datasets/bus-blinds.csv b/assets/datasets/bus-blinds.csv
new file mode 100644
index 0000000..802245e
--- /dev/null
+++ b/assets/datasets/bus-blinds.csv
@@ -0,0 +1,5164 @@
+Route,Blind,51.4309209,-0.0936496
+1,Tottenham Court Road,51.516765,-0.1308319
+1,Holborn,51.5179371,-0.1106193
+1,Aldwych,51.5117949,-0.1193297
+1,Waterloo,51.4309209,-0.0936496
+1,Elephant & Castle,51.49380679999999,-0.0977981
+1,Elephant & Castle,51.49380679999999,-0.0977981
+1,Bricklayer's Arms,51.4661409,-0.2174147
+1,Surrey Quays,51.4944172,-0.0383063
+1,Southwark Park Road,51.493047,-0.07343890000000002
+1,Canada Water,51.4971488,-0.0471107
+2,Marylebone,51.5188746,-0.1498955
+2,Marble Arch,51.5135032,-0.158161
+2,Hyde Park Corner,51.5029347,-0.1508562
+2,Victoria,51.4309209,-0.0936496
+2,Vauxhall,51.4309209,-0.0936496
+2,Stockwell,51.4309209,-0.0936496
+2,Brixton,51.4612794,-0.1156148
+2,Brixton,51.4612794,-0.1156148
+2,Tulse Hill Station,51.43986,-0.10505
+2,West Norwood,51.427905,-0.1002486
+3,Regent Street,51.5080333,-0.133591
+3,Piccadilly Circus,51.5101699,-0.1348241
+3,"Whitehall, Horse Guards",51.5048768,-0.1243897
+3,"Whitehall, Horse Guards",51.5048768,-0.1243897
+3,Parliament Square,51.5007668,-0.1261294
+3,Lambeth Bridge,51.4945633,-0.123211
+3,Kennington Lane,51.4911995,-0.1034744
+3,Kennington Church,51.5026934,-0.19148
+3,Brixton,51.4612794,-0.1156148
+3,Brixton,51.4612794,-0.1156148
+3,"Brixton, Morval Road",51.4560094,-0.1133047
+3,South Croxted Road,51.4354963,-0.09071219999999999
+3,Crystal Palace,51.4197233,-0.0830638
+4,Archway,51.4309209,-0.0936496
+4,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+4,Finsbury Park Station,51.5646425,-0.1058553
+4,Highbury Barn,51.5569649,-0.0979656
+4,Highbury & Islington,51.5569649,-0.0979656
+4,"Islington, Angel",51.5366523,-0.1029852
+4,Barbican,51.5202077,-0.09378639999999999
+4,St. Paul's,51.6045473,-0.1873796
+4,Ludgate Circus,51.513956,-0.1045484
+4,Aldwych,51.5119745,-0.1189746
+4,Waterloo,51.5048541,-0.1136621
+4,Waterloo,51.5048541,-0.1136621
+5,Romford Market,51.5790739,0.1813886
+5,Romford Station,51.577076,0.178319
+5,Roneo Corner,51.5654396,0.1884167
+5,Becontree Heath,51.5609465,0.1488995
+5,Five Elms,51.5537943,0.1416476
+5,Bennett's Castle Lane,51.5613931,0.1248746
+5,Fair Cross,51.54162059999999,0.08352939999999999
+5,Barking,51.536563,0.075766
+5,Barking,51.536563,0.075766
+5,Newham Town Hall,51.53280239999999,0.0551608
+5,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+5,"Upton Park, Boleyn",51.5305005,0.0384915
+5,"Plaistow, Balaam Street",51.5226426,0.0223686
+5,"Canning Town, Barking Road",51.53044569999999,0.038323
+5,Canning Town,51.5189494,0.0132
+6,"Willesden, Bus Garage",51.5474482,-0.2394372
+6,Kensal Rise,51.5345071,-0.2250186
+6,Queen's Park,51.5345448,-0.2043853
+6,Edgware Road Station,51.51988249999999,-0.1678336
+6,Marble Arch,51.5132872,-0.1595743
+6,Portman Square,51.5160186,-0.1547182
+6,Oxford Circus,51.51651950000001,-0.1307199
+6,Oxford Circus,51.51651950000001,-0.1307199
+6,Oxford Circus,51.51651950000001,-0.1307199
+6,Piccadilly Circus,51.5101283,-0.1348339
+6,Trafalgar Square,51.5085695,-0.1272433
+6,Aldwych,51.51200499999999,-0.1189687
+7,East Acton,51.5127758,-0.2476803
+7,East Acton,51.5127758,-0.2476803
+7,North Pole Road,51.5199025,-0.2255136
+7,Ladbroke Grove,51.5082078,-0.2035147
+7,Chepstow Road,51.5159207,-0.1955695
+7,Paddington,51.4309209,-0.0936496
+7,Edgware Road Station,51.51988249999999,-0.1678336
+7,Marble Arch,51.5133592,-0.1594906
+7,Oxford Circus,51.5162288,-0.1319806
+8,Bow Church,51.5287753,-0.0167013
+8,Old Ford,51.53210989999999,-0.0429126
+8,"Roman Road, Grove Road",51.531048,-0.03955699999999999
+8,Shoreditch,51.5229106,-0.0777472
+8,Liverpool Street,51.5176795,-0.084275
+8,St. Paul's,51.60466,-0.1872059
+8,City Thameslink,51.5140438,-0.1033475
+8,Holborn,51.5180284,-0.1105998
+8,Holborn,51.5180284,-0.1105998
+8,Tottenham Court Road,51.5171962,-0.1308925
+8,Oxford Circus,51.5163033,-0.1311388
+9,Aldwych,51.5120957,-0.1189441
+9,Trafalgar Square,51.5085695,-0.1272433
+9,Green Park,51.4309209,-0.0936496
+9,Hyde Park Corner,51.5029347,-0.1508562
+9,Hyde Park Corner,51.5029347,-0.1508562
+9,Royal Albert Hall,51.5009088,-0.177366
+9,"Kensington, Palace Gate",51.5010142,-0.1843302
+9,"Kensington, Holland Road",51.49713879999999,-0.2069513
+9,Hammersmith,51.491187,-0.223731
+10,Hammersmith,51.4934634,-0.2236314
+10,"Kensington, Holland Road",51.49748289999999,-0.2066984
+10,"Kensington, Palace Gate",51.4999555,-0.1836283
+10,Royal Albert Hall,51.5009088,-0.177366
+10,Hyde Park Corner,51.5029347,-0.1508562
+10,Marble Arch,51.5133563,-0.1595136
+10,Oxford Circus,51.5165182,-0.1308243
+10,Euston,51.5314825,-0.1344752
+10,King's Cross,51.5347488,-0.1245845
+11,Fulham Broadway,51.4799039,-0.1958386
+11,Fulham Broadway,51.4799039,-0.1958386
+11,"Chelsea, World's End",51.4810423,-0.1786311
+11,Sloane Square,51.4928113,-0.156879
+11,"Victoria, Coach Station",51.4924744,-0.1482485
+11,Victoria,51.4309209,-0.0936496
+11,Parliament Square,51.5007668,-0.1261294
+11,"Whitehall, Horse Guards",51.5049558,-0.1254432
+11,Trafalgar Square,51.5085695,-0.1272433
+11,Aldwych,51.5122788,-0.1191599
+11,Ludgate Circus,51.51432699999999,-0.1038489
+11,Mansion House,51.5127309,-0.08894429999999999
+11,Liverpool Street,51.5188119,-0.0796944
+12,Oxford Circus,51.5165184,-0.1309686
+12,Piccadilly Circus,51.5101227,-0.1347793
+12,"Whitehall, Horseguards",51.5049111,-0.1273704
+12,Parliament Square,51.5007668,-0.1261294
+12,Lambeth North,51.4935082,-0.1178424
+12,Elephant & Castle,51.49358119999999,-0.0985682
+12,"Camberwell Road, Medlar Street",51.4793161,-0.0941097
+12,Camberwell Green,51.47460479999999,-0.0933951
+12,Peckham,51.47032369999999,-0.0673872
+12,Peckham Rye,51.4645765,-0.0657682
+12,Dulwich Library,51.4488677,-0.07447669999999999
+13,North Finchley,51.6135087,-0.1754198
+13,"Finchley, Church End",51.604606,-0.1882833
+13,Golders Green,51.5740013,-0.1987725
+13,Finchley Road & Frognal,51.5503454,-0.180462
+13,Swiss Cottage,51.5425872,-0.1724737
+13,St John's Wood,51.5343581,-0.1742065
+13,Baker Street Station,51.5231548,-0.156863
+13,Baker Street Station,51.5231548,-0.156863
+13,Baker Street Station,51.5231548,-0.156863
+13,Portman Square,51.5163404,-0.1549876
+13,Portman Square,51.5163404,-0.1549876
+13,Marble Arch,51.5134505,-0.1594581
+13,"Park Lane, Hilton Hotel",51.5055096,-0.1503864
+13,Victoria,51.4309209,-0.0936496
+14,Putney Heath,51.4366227,-0.2304487
+14,Putney Station,51.4611807,-0.2164913
+14,Putney Bridge,51.4679357,-0.2118155
+14,Fulham Broadway,51.4802127,-0.1969798
+14,South Kensington,51.4953291,-0.1789909
+14,Hyde Park Corner,51.4309209,-0.0936496
+14,Green Park,51.4309209,-0.0936496
+14,Piccadilly Circus,51.5103455,-0.13441
+14,Tottenham Court Road,51.5170065,-0.1305656
+14,Tottenham Court Road,51.5170065,-0.1305656
+14,Warren Street,51.5241056,-0.1390055
+14,Warren Street,51.5241056,-0.1390055
+15,Blackwall,51.486813,0.007257999999999999
+15,"Poplar, All Saints",51.5105521,-0.0118612
+15,"Limehouse, Burdett Road",51.5236032,-0.0343309
+15,"Stepney, Arbour Square",51.514508,-0.04844690000000001
+15,Aldgate,51.5150654,-0.075847
+15,Aldgate,51.5150654,-0.075847
+15,Tower Hill,51.50973920000001,-0.0785773
+15,Cannon Street,51.5126702,-0.09531519999999999
+15,St. Paul's,51.6050001,-0.187336
+15,Ludgate Circus,51.5140488,-0.1043187
+15,Aldwych,51.5122751,-0.1188606
+15,Trafalgar Square,51.508039,-0.128069
+16,Cricklewood Bus Garage,51.56195959999999,-0.2224221
+16,Cricklewood Broadway,51.5529089,-0.2104297
+16,Kilburn High Road Station,51.537243,-0.192318
+16,Kilburn High Road Station,51.537243,-0.192318
+16,Edgware Road Station,51.51988249999999,-0.1678336
+16,Marble Arch,51.51335049999999,-0.1595594
+16,"Park Lane, Hilton Hotel",51.5055096,-0.1503864
+16,Victoria,51.4309209,-0.0936496
+17,Archway,51.4309209,-0.0936496
+17,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+17,King's Cross,51.5347488,-0.1245845
+17,King's Cross,51.5347488,-0.1245845
+17,Ludgate Circus,51.5140505,-0.1043191
+17,St. Paul's,51.6050631,-0.1872825
+17,London Bridge,51.5078788,-0.0877321
+18,Sudbury,51.5142858,0.0640934
+18,Wembley Stadium,51.55602469999999,-0.2796177
+18,Stonebridge Park,51.54571809999999,-0.2615303
+18,Craven Park,51.54065989999999,-0.2558117
+18,Craven Park,51.54065989999999,-0.2558117
+18,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+18,"Harrow Road, Elgin Avenue",51.520765,-0.1810053
+18,"Harrow Road, Elgin Avenue",51.520765,-0.1810053
+18,"Harrow Road, Warwick Avenue",51.5208194,-0.1809035
+18,Paddington Green,51.5207833,-0.1734463
+18,Baker Street Station,51.5231548,-0.156863
+18,Warren Street,51.52412,-0.1396242
+18,Euston,51.53017,-0.123333
+19,Finsbury Park Station,51.5646425,-0.1058553
+19,Highbury Barn,51.5569649,-0.0979656
+19,Highbury & Islington,51.5569649,-0.0979656
+19,Islington Green,51.5362387,-0.1019279
+19,Rosebery Avenue,51.5239515,-0.1113229
+19,Holborn,51.5178118,-0.1098122
+19,Holborn,51.5178118,-0.1098122
+19,Piccadilly Circus,51.5101323,-0.1350825
+19,Hyde Park Corner,51.5029347,-0.1508562
+19,Hyde Park Corner,51.5029347,-0.1508562
+19,Sloane Square,51.4938898,-0.1552165
+19,"Battersea Bridge, South Side",51.4811674,-0.1725411
+20,Walthamstow Central,51.5830128,-0.019886
+20,"Leyton, Bakers Arms",51.5749185,-0.013549
+20,Whipps Cross,51.581499,0.0001219
+20,Woodford Green,51.6092549,0.0405521
+20,Woodford Wells,51.6148287,0.0282889
+20,Loughton,51.655942,0.068161
+20,Debden,51.6042352,0.04159529999999999
+21,"Lewisham, Shopping Centre",51.46115090000001,-0.0073177
+21,"Lewisham, Jerrard Street",51.4650045,-0.0164722
+21,New Cross Gate,51.4749904,-0.0403466
+21,New Cross Gate,51.4749904,-0.0403466
+21,Bricklayer's Arms,51.4661409,-0.2174147
+21,London Bridge,51.5078788,-0.0877321
+21,"Moorgate, Finsbury Square",51.5202193,-0.08877170000000001
+21,"Hoxton, Baring Street",51.5370603,-0.0886892
+21,Newington Green,51.5513088,-0.0844365
+22,Putney Common,51.4674099,-0.2282218
+22,Putney Church,51.4596431,-0.2141257
+22,Putney Bridge,51.4582148,-0.1979725
+22,Parsons Green,51.4731883,-0.2008051
+22,"Chelsea, World's End",51.4810423,-0.1786311
+22,Sloane Square,51.4928113,-0.156879
+22,Knightsbridge,51.4991195,-0.1644394
+22,Hyde Park Corner,51.5029347,-0.1508562
+22,Green Park,51.4309209,-0.0936496
+22,Piccadilly Circus,51.5101327,-0.1350772
+23,Westbourne Park,51.52093499999999,-0.2007649
+23,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+23,"Notting Hill, Westbourne Grove",51.5155424,-0.1893047
+23,Paddington,51.4309209,-0.0936496
+23,Paddington,51.4309209,-0.0936496
+23,Paddington,51.4309209,-0.0936496
+23,Edgware Road Station,51.51988249999999,-0.1678336
+23,Marble Arch,51.5134632,-0.1593655
+23,Marble Arch,51.5134632,-0.1593655
+23,Oxford Circus,51.5162691,-0.1312544
+23,Oxford Circus,51.5162691,-0.1312544
+23,Piccadilly Circus,51.5101331,-0.1350718
+23,Trafalgar Square,51.508039,-0.128069
+23,Aldwych,51.5124243,-0.1190358
+23,Ludgate Circus,51.5140556,-0.1043203
+23,St. Paul's,51.5064502,-0.2935763
+23,Liverpool Street,51.517297,-0.0823724
+24,Pimlico,51.490744,-0.1403619
+24,Victoria,51.49554149999999,-0.1435602
+24,Parliament Square,51.5007668,-0.1261294
+24,Trafalgar Square,51.508039,-0.128069
+24,Tottenham Court Road,51.5180841,-0.1315221
+24,Tottenham Court Road,51.5180841,-0.1315221
+24,Warren Street,51.5237815,-0.1407361
+24,Mornington Crescent,51.5335427,-0.1406798
+24,Camden Town,51.5390261,-0.1425516
+24,Chalk Farm,51.5444834,-0.152158
+24,Hampstead Heath,51.5608294,-0.1629416
+25,Oxford Circus,51.5164398,-0.1324736
+25,Holborn,51.5181161,-0.1104144
+25,Holborn,51.5181161,-0.1104144
+25,City Thameslink,51.5140438,-0.1033475
+25,St. Paul's,51.50677959999999,-0.2927933
+25,Bank,51.4309209,-0.0936496
+25,Aldgate,51.5134081,-0.0770975
+25,Mile End,51.52354529999999,-0.0330122
+25,Bow Church,51.5287753,-0.0167013
+25,Bow Church,51.5287753,-0.0167013
+25,Stratford,51.5426313,-0.0010369
+25,"Forest Gate, Police Station",51.5467822,0.0309995
+25,Manor Park,51.4568223,-0.0013946
+25,Ilford Broadway,51.556619,0.076251
+25,Ilford,51.556619,0.076251
+26,Hackney Wick,51.544579,-0.0256935
+26,"Hackney, Well Street",51.5399525,-0.0546394
+26,Ash Grove,51.4069459,-0.0561859
+26,Shoreditch,51.5229106,-0.0777472
+26,Shoreditch,51.5229106,-0.0777472
+26,Liverpool Street,51.5172811,-0.0822137
+26,Mansion House,51.51300699999999,-0.08950899999999999
+26,Aldwych,51.5130774,-0.1162049
+26,Waterloo,51.5048541,-0.1136621
+27,"Chiswick, Business Park",51.4930604,-0.2748696
+27,"Stamford Brook, Bus Garage",51.4309209,-0.0936496
+27,Hammersmith,51.491187,-0.223731
+27,"Kensington, Holland Road",51.4975402,-0.2073943
+27,"Kensington, Holland Road",51.4975402,-0.2073943
+27,Notting Hill Gate,51.5091914,-0.1947424
+27,Paddington,51.4309209,-0.0936496
+27,Edgware Road Station,51.51988249999999,-0.1678336
+27,Baker Street Station,51.5231548,-0.156863
+27,Warren Street,51.5237196,-0.1409656
+27,Mornington Crescent,51.5338447,-0.1406486
+27,Camden Town,51.5390261,-0.1425516
+27,Chalk Farm,51.5444834,-0.152158
+28,Kensal Rise,51.5345071,-0.2250186
+28,"Harrow Road, Elgin Avenue",51.520765,-0.1810053
+28,Westbourne Park,51.51769299999999,-0.194941
+28,Notting Hill Gate,51.5096114,-0.1943814
+28,"Kensington, Holland Road",51.4978412,-0.2072414
+28,"North End Road, Lillie Road",51.4857738,-0.2013501
+28,Fulham Broadway,51.4803466,-0.1969636
+28,New Kings Road,51.4733974,-0.1978029
+28,"Wandsworth Bridge, South Side",51.4651939,-0.1880094
+28,"Wandsworth, Town Hall",51.4570227,-0.191114
+28,Wandsworth,51.45837299999999,-0.1891356
+29,Wood Green,51.5971722,-0.1098021
+29,Wood Green,51.5971722,-0.1098021
+29,Turnpike Lane Station,51.5904278,-0.1027587
+29,Finsbury Park Station,51.5646425,-0.1058553
+29,Finsbury Park Station,51.5646425,-0.1058553
+29,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+29,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+29,Camden Town,51.5390261,-0.1425516
+29,Mornington Crescent,51.533949,-0.1406149
+29,Warren Street,51.5236972,-0.141188
+29,Tottenham Court Road,51.5180123,-0.131601
+29,Trafalgar Square,51.508039,-0.128069
+29,Trafalgar Square,51.508039,-0.128069
+30,Marble Arch,51.51333700000001,-0.1596664
+30,Portman Square,51.5156011,-0.1569817
+30,Baker Street Station,51.5231548,-0.156863
+30,Warren Street,51.52360400000001,-0.1416947
+30,Euston,51.530473,-0.1232482
+30,King's Cross,51.5347488,-0.1245845
+30,Islington Angel,51.5357662,-0.1025254
+30,Islington Green,51.5357662,-0.1025254
+30,Highbury & Islington,51.5569649,-0.0979656
+30,Highbury & Islington,51.5569649,-0.0979656
+30,Mildmay Park,51.54806050000001,-0.0838744
+30,Hackney Central,51.5482344,-0.05738749999999999
+30,Hackney Wick,51.544579,-0.0256935
+31,Camden Town,51.5390261,-0.1425516
+31,Chalk Farm,51.5444834,-0.152158
+31,Swiss Cottage,51.5425872,-0.1724737
+31,Swiss Cottage,51.5425872,-0.1724737
+31,South Hampstead Station,51.4309209,-0.0936496
+31,Kilburn High Road Station,51.539813,-0.1985291
+31,Kilburn High Road Station,51.539813,-0.1985291
+31,Kilburn Park,51.4309209,-0.0936496
+31,"Maida Hill, The Chippenham",51.5243627,-0.2017331
+31,Westbourne Park,51.51769299999999,-0.194941
+31,Westbourne Park,51.51769299999999,-0.194941
+31,Notting Hill Gate,51.51029399999999,-0.1975027
+31,Holland Park Roundabout,51.5042925,-0.217039
+31,White City,51.51146199999999,-0.2376332
+32,Edgware,51.61548819999999,-0.2609598
+32,Burnt Oak Broadway,51.602753,-0.2700278
+32,"Colindale, Superstores",51.5942575,-0.2607018
+32,West Hendon Broadway,51.5772325,-0.2392682
+32,Staples Corner,51.5714404,-0.2319415
+32,Cricklewood Bus Garage,51.56195959999999,-0.2224221
+32,Cricklewood Broadway,51.5567072,-0.2153734
+32,Kilburn Park,51.53504119999999,-0.1938988
+33,"Fulwell, Stanley Road",51.4285891,-0.3426514
+33,Teddington,51.4268694,-0.3338681
+33,Twickenham,51.4453043,-0.3375429
+33,Richmond,51.4309209,-0.0936496
+33,"East Sheen, Queen's Road",51.46676369999999,-0.2595881
+33,Barnes Common,51.4681254,-0.2413995
+33,"Barnes, Red Lion",51.4755063,-0.2389859
+33,Hammersmith,51.491187,-0.223731
+34,Barnet Church,51.6526856,-0.1992227
+34,"Barnet, Odeon",51.64663059999999,-0.1865655
+34,Whetstone,51.4309209,-0.0936496
+34,New Southgate,51.61100099999999,-0.135469
+34,Arnos Grove,51.6222675,-0.1278413
+34,"Palmers Green, North Circular Road",51.6214872,-0.1075657
+34,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+34,North Middlesex Hospital,51.6131618,-0.0735832
+34,"Edmonton, Angel",51.6088564,-0.04952819999999999
+34,"Angel Road, Eleys Estate",51.6169024,-0.0460262
+34,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+34,Walthamstow Central,51.5830128,-0.019886
+35,Clapham Junction,51.4651737,-0.1708113
+35,Clapham Common,51.4589252,-0.1493071
+35,Brixton,51.4612794,-0.1156148
+35,Brixton,51.4612794,-0.1156148
+35,Camberwell Green,51.47418649999999,-0.09230569999999999
+35,Elephant & Castle,51.49384080000001,-0.0979717
+35,Elephant & Castle,51.49384080000001,-0.0979717
+35,London Bridge,51.5078788,-0.0877321
+35,London Bridge,51.5078788,-0.0877321
+35,Shoreditch,51.5229106,-0.0777472
+36,Queen's Park,51.5345448,-0.2043853
+36,"Harrow Road, Elgin Avenue",51.520765,-0.1810053
+36,Paddington,51.4309209,-0.0936496
+36,Marble Arch,51.5133312,-0.1597123
+36,Hyde Park Corner,51.5029347,-0.1508562
+36,Vauxhall,51.4309209,-0.0936496
+36,Camberwell Green,51.47418649999999,-0.09230569999999999
+36,Peckham,51.47032369999999,-0.0673872
+36,Peckham,51.47032369999999,-0.0673872
+36,New Cross Gate,51.4749904,-0.0403466
+37,Putney Heath,51.4535043,-0.2295163
+37,Wandsworth,51.45837299999999,-0.1891356
+37,Clapham Junction,51.4651737,-0.1708113
+37,Clapham Junction,51.4651737,-0.1708113
+37,Clapham Common,51.4589252,-0.1493071
+37,Brixton,51.4612794,-0.1156148
+37,Herne Hill,51.4609208,-0.0985404
+37,East Dulwich,51.4545635,-0.0732101
+37,Peckham Rye,51.464316,-0.06563229999999999
+37,Peckham,51.47032369999999,-0.0673872
+38,Clapton Pond,51.5561061,-0.05490830000000001
+38,Hackney Central,51.5482344,-0.05738749999999999
+38,Mildmay Park,51.5483296,-0.0839477
+38,Islington Green,51.5356013,-0.1033279
+38,Islington Angel,51.5356013,-0.1033279
+38,Rosebery Avenue,51.5244006,-0.1107607
+38,Holborn,51.51811559999999,-0.1104102
+38,Piccadilly Circus,51.5112652,-0.1343363
+38,Hyde Park Corner,51.4309209,-0.0936496
+38,Victoria,51.4309209,-0.0936496
+39,Putney Bridge,51.4669712,-0.2129034
+39,Putney Station,51.4611807,-0.2164913
+39,Putney Heath,51.4535043,-0.2295163
+39,"Southfields, Granville Road",51.4497918,-0.2017799
+39,Wandsworth,51.45837299999999,-0.1891356
+39,Clapham Junction,51.4651737,-0.1708113
+40,Dulwich Library,51.4488677,-0.07447669999999999
+40,East Dulwich,51.4545635,-0.0732101
+40,Camberwell Green,51.4755856,-0.09233469999999999
+40,Elephant & Castle,51.4938192,-0.0981413
+40,Elephant & Castle,51.4938192,-0.0981413
+40,London Bridge,51.5078788,-0.0877321
+40,Aldgate,51.5133004,-0.0774081
+41,Archway,51.4694651,-0.2531938
+41,Hornsey Rise,51.5710037,-0.1243396
+41,Crouch End,51.5819979,-0.1221464
+41,Hornsey,51.5872715,-0.1103806
+41,West Green,51.586254,-0.0867628
+41,"Green Lanes, West Green Road",51.5841132,-0.07532190000000001
+41,Seven Sisters,51.582652,-0.0747232
+41,Tottenham Hale,51.5892808,-0.06105049999999999
+42,"East Dulwich, Sainsburys",51.4624191,-0.0834805
+42,Camberwell Green,51.4755856,-0.09233469999999999
+42,Camberwell Green,51.4755856,-0.09233469999999999
+42,Bricklayer's Arms,51.4661409,-0.2174147
+42,Tower Gateway,51.5106312,-0.0737553
+42,Aldgate,51.5169305,-0.064391
+42,Liverpool Street,51.5169921,-0.0810587
+43,Friern Barnet,51.6141967,-0.1540148
+43,Muswell Hill,51.5911816,-0.1443015
+43,Muswell Hill,51.5911816,-0.1443015
+43,Archway,51.4309209,-0.0936496
+43,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+43,Highbury & Islington,51.5569649,-0.0979656
+43,Islington Angel,51.5354865,-0.103688
+43,Angel,51.4309209,-0.0936496
+43,Old Street Station,51.4309209,-0.0936496
+43,Moorgate,51.5163044,-0.0890892
+43,Bank Station,51.4309209,-0.0936496
+43,London Bridge,51.5078788,-0.0877321
+44,Victoria,51.4309209,-0.0936496
+44,Battersea Park Station,51.47696,-0.14751
+44,"Battersea, Latchmere Road",51.4701066,-0.1644671
+44,Wandsworth,51.45837299999999,-0.1891356
+44,Wandsworth,51.45837299999999,-0.1891356
+44,Wandsworth,51.45837299999999,-0.1891356
+44,"Garratt Lane, Wimbledon Road",51.4324265,-0.1823902
+44,Tooting Broadway,51.427867,-0.1678142
+44,Tooting Station,51.41986989999999,-0.16136
+45,King's Cross,51.5347488,-0.1245845
+45,"Farringdon Street, Smithfield",51.5179207,-0.1055172
+45,Ludgate Circus,51.5140743,-0.1043248
+45,Camberwell Green,51.4755856,-0.09233469999999999
+45,Brixton,51.4612794,-0.1156148
+45,Brixton,51.4612794,-0.1156148
+45,Clapham Park,51.4476066,-0.1431943
+46,Paddington,51.4309209,-0.0936496
+46,Warwick Avenue,51.5242448,-0.1861688
+46,Swiss Cottage,51.5425872,-0.1724737
+46,Hampstead Heath,51.5608294,-0.1629416
+46,King's Cross,51.5347488,-0.1245845
+46,King's Cross,51.5347488,-0.1245845
+46,St Bartholomew's Hospital,51.51749599999999,-0.1000463
+47,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+47,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+47,"Deptford, Church Street",51.4746631,-0.0239358
+47,Deptford Bridge,51.4744133,-0.0214318
+47,Surrey Quays,51.4944172,-0.0383063
+47,Canada Water,51.4962989,-0.0482742
+47,London Bridge,51.5072178,-0.1275862
+47,Liverpool Street,51.5169916,-0.08105749999999999
+47,"Tower Bridge Road, Druid Street",51.5003867,-0.07642150000000002
+47,Shoreditch,51.5229106,-0.0777472
+48,Walthamstow Central,51.5830128,-0.019886
+48,Leyton Bakers Arms,51.5749185,-0.013549
+48,Clapton Pond,51.5561061,-0.05490830000000001
+48,Clapton Pond,51.5561061,-0.05490830000000001
+48,Clapton Pond,51.5561061,-0.05490830000000001
+48,Hackney Well Street,51.5400447,-0.0529401
+48,Ash Grove,51.47989889999999,-0.3919869
+48,Shoreditch,51.5229106,-0.0777472
+48,Liverpool Street,51.5169915,-0.0810573
+48,Monument,51.4309209,-0.0936496
+48,London Bridge,51.50949749999999,-0.0872447
+48,London Bridge,51.50949749999999,-0.0872447
+49,Clapham Junction,51.4309209,-0.0936496
+49,"Battersea, Latchmere Road",51.4701063,-0.1641724
+49,"Battersea Bridge, South Side",51.4811674,-0.1725411
+49,South Kensington,51.4953291,-0.1789909
+49,"Kensington, Palace Gate",51.4997084,-0.1839913
+49,"Kensington, Holland Road",51.4981321,-0.2082809
+49,Holland Park Roundabout,51.5042925,-0.217039
+49,White City,51.51146199999999,-0.2376332
+50,Croydon Town Centre,51.3769529,-0.0956895
+50,West Croydon,51.3684193,-0.0998425
+50,"Thornton Heath, High Street",51.3985843,-0.0946916
+50,Norbury,51.4085878,-0.1213899
+50,"Streatham, Green Lane",51.40957599999999,-0.1064891
+50,Streatham Station,51.4259857,-0.131308
+50,Streatham Hill Station,51.4382009,-0.1270706
+50,Clapham Park,51.4476066,-0.1431943
+50,Clapham Common,51.4589252,-0.1493071
+50,Stockwell,51.4698988,-0.1203349
+51,Woolwich,51.4894752,0.06758829999999999
+51,Plumstead Common,51.4810415,0.0713811
+51,Welling Station,51.4648,0.10172
+51,Welling Corner,51.4626258,0.1081541
+51,Sidcup Station,51.4339345,0.1038351
+51,Foots Cray,51.4174447,0.1210622
+51,St Mary Cray Station,51.3957762,0.1071945
+51,"Orpington, Perry Hall Road",51.3822834,0.1033862
+51,Orpington War Memorial,51.373203,0.09753479999999999
+51,Orpington Station,51.37329,0.08911999999999999
+52,Victoria,51.5110756,-0.1077217
+52,Hyde Park Corner,51.5029347,-0.1508562
+52,Hyde Park Corner,51.5029347,-0.1508562
+52,Royal Albert Hall,51.5009088,-0.177366
+52,Notting Hill Gate,51.50948649999999,-0.1953925
+52,Notting Hill Gate,51.50948649999999,-0.1953925
+52,Notting Hill Gate,51.50948649999999,-0.1953925
+52,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+52,Kensal Rise,51.5345071,-0.2250186
+52,"Willesden, Bus Garage",51.5474482,-0.2394372
+53,Plumstead Station,51.4896774,0.0847463
+53,Plumstead Common,51.4823231,0.0695262
+53,Woolwich,51.4894752,0.06758829999999999
+53,Woolwich,51.4894752,0.06758829999999999
+53,Charlton Village,51.4309209,-0.0936496
+53,"Blackheath, Royal Standard",51.4779946,0.0202001
+53,"Blackheath, Royal Standard",51.4779946,0.0202001
+53,Deptford Bridge,51.4743135,-0.0215605
+53,New Cross,51.4769047,-0.0336897
+53,New Cross Gate,51.4749904,-0.0403466
+53,Bricklayer's Arms,51.4661409,-0.2174147
+53,Elephant & Castle,51.49384080000001,-0.0979717
+53,Lambeth North,51.4935082,-0.1178424
+53,Lambeth North,51.4935082,-0.1178424
+53,Parliament Square,51.5007668,-0.1261294
+53,"Whitehall, Horse Guards",51.506168,-0.1268165
+54,Elmers End,51.39749,-0.0474767
+54,"Beckenham, War Memorial",51.406914,-0.0320175
+54,"Beckenham, War Memorial",51.406914,-0.0320175
+54,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+54,"Catford, Town Centre",51.4453954,-0.0160913
+54,"Catford, Town Centre",51.4453954,-0.0160913
+54,Lewisham Shopping Centre,51.46175909999999,-0.0119106
+54,Blackheath Village,51.4652738,0.0094822
+54,Charlton Village,51.4792826,0.0248846
+54,"Blackheath, Royal Standard",51.4779946,0.0202001
+54,Woolwich,51.4894752,0.06758829999999999
+55,"Leyton, Bakers Arms",51.5749185,-0.013549
+55,Clapton Pond,51.5561061,-0.05490830000000001
+55,Clapton Pond,51.5561061,-0.05490830000000001
+55,Clapton Pond,51.5561061,-0.05490830000000001
+55,Hackney Well Street,51.5409698,-0.0502274
+55,Ash Grove,51.6354767,-0.0751363
+55,Shoreditch,51.5229106,-0.0777472
+55,Old Street Station,51.5256719,-0.0874922
+55,Old Street Station,51.5256719,-0.0874922
+55,Clerkenwell Green,51.5227521,-0.1059866
+55,Holborn,51.5181148,-0.1104047
+55,Holborn,51.5181148,-0.1104047
+55,Oxford Circus,51.5161662,-0.1326994
+56,Whipps Cross,51.581499,0.0001219
+56,"Leyton, Bakers Arms",51.5749185,-0.013549
+56,Clapton Pond,51.5561061,-0.05490830000000001
+56,Clapton Pond,51.5561061,-0.05490830000000001
+56,Dalston Junction,51.5459999,-0.0751485
+56,Mildmay Park,51.54948479999999,-0.0842682
+56,Islington Green,51.5354865,-0.103688
+56,Islington Angel,51.5346761,-0.1042905
+56,Barbican,51.5202077,-0.09378639999999999
+56,St Bartholomew's Hospital,51.51749599999999,-0.1000463
+57,Kingston,51.41233,-0.300689
+57,Kingston Hospital,51.4148229,-0.2824061
+57,Coombe Lane,51.4098586,-0.2361138
+57,Raynes Park,51.4084257,-0.2298751
+57,Wimbledon,51.41833889999999,-0.2206288
+57,Wimbledon,51.41833889999999,-0.2206288
+57,Colliers Wood,51.41704439999999,-0.1778555
+57,"Merton, Bus Garage",51.4165431,-0.1813083
+57,"Merton, Bus Garage",51.4165431,-0.1813083
+57,Tooting Broadway,51.427867,-0.1678142
+57,"Streatham, St Leonard's Church",51.42926610000001,-0.1311095
+57,Streatham Hill Station,51.4382009,-0.1270706
+57,Clapham Park,51.4476066,-0.1431943
+58,"East Ham, Central Park",51.5293175,0.0527634
+58,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+58,"Upton Park, Boleyn",51.5305005,0.0384915
+58,"Forest Gate, Police Station",51.5467822,0.0309995
+58,Wanstead Park,51.5610723,0.0417191
+58,"Leyton, Downsell Road",51.553296,-0.0028916
+58,"Leyton, Grange Park Road",51.5651058,-0.0141172
+58,Markhouse Corner,51.5779407,-0.0304034
+58,Walthamstow Central,51.5830128,-0.019886
+59,"Streatham Hill, Telford Avenue",51.44235,-0.1305407
+59,Brixton,51.4612794,-0.1156148
+59,Brixton,51.4612794,-0.1156148
+59,Kennington Church,51.504101,-0.193068
+59,Waterloo,51.5045274,-0.1130244
+59,Aldwych,51.51324409999999,-0.1172819
+59,Holborn,51.5181147,-0.1104034
+59,Russell Square,51.5212546,-0.1242077
+59,Euston,51.5268812,-0.1315678
+59,King's Cross,51.5347488,-0.1245845
+60,Old Coulsdon,51.298482,-0.114175
+60,"Coulsdon, Chaldon Way",51.3107704,-0.1340667
+60,Coulsdon,51.319941,-0.141267
+60,Purley,51.339228,-0.119711
+60,Purley,51.339228,-0.119711
+60,"South Croydon, Bus Garage",51.3544903,-0.0968822
+60,"South Croydon, South End",51.36546999999999,-0.09921999999999999
+60,Croydon Town Centre,51.3769529,-0.0956895
+60,West Croydon,51.3684193,-0.0998425
+60,Thornton Heath Pond,51.3941232,-0.1146955
+60,Pollards Hill,51.4000406,-0.1332582
+60,Streatham Vale,51.4165952,-0.1384217
+60,Streatham Station,51.4259857,-0.131308
+61,Chislehurst,51.412626,0.077487
+61,"Orpington, Perry Hall Road",51.3822977,0.1023434
+61,Orpington Walnuts Centre,51.3773656,0.1007092
+61,Orpington War Memorial,51.373203,0.09753479999999999
+61,Orpington Station,51.374843,0.09421399999999999
+61,Locksbottom,51.3673231,0.0547259
+61,"Bromley Common, Bus Garage",51.38774,0.0363217
+61,"Bromley Common, Crown Lane",51.3890567,0.0384357
+61,Bromley South,51.406025,0.013156
+61,Bromley North,51.406025,0.013156
+62,Marks Gate,51.5901971,0.1424532
+62,Chadwell Heath,51.5722283,0.141995
+62,"Becontree, Green Lane",51.5589129,0.08329829999999999
+62,"Ripple Road, Lodge Avenue",51.5327114,0.1076005
+62,Fair Cross,51.5425708,0.0822502
+62,Barking,51.536563,0.075766
+62,"Barking, Gascoigne Estate",51.529678,0.08277400000000001
+63,Honor Oak,51.4494778,-0.0448232
+63,Peckham Rye,51.4635527,-0.06519749999999999
+63,Peckham,51.47032369999999,-0.0673872
+63,Bricklayer's Arms,51.4661409,-0.2174147
+63,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+63,Elephant & Castle,51.49384080000001,-0.0979717
+63,"Farringdon Street, Smithfield",51.5151388,-0.1048555
+63,Clerkenwell Green,51.5227521,-0.1059866
+63,King's Cross,51.5347488,-0.1245845
+64,Thornton Heath Pond,51.3941232,-0.1146955
+64,West Croydon,51.3684193,-0.0998425
+64,East Croydon,51.3769529,-0.0956895
+64,Selsdon,51.34372279999999,-0.061975
+64,Addington Village,51.35922559999999,-0.0286665
+64,New Addington,51.348184,-0.017094
+65,Chessington,51.363583,-0.296254
+65,Kingston,51.41233,-0.300689
+65,"Kingston, Cromwell Road",51.4952712,-0.1790609
+65,Ham,51.4309209,-0.0936496
+65,Richmond,51.46131099999999,-0.303742
+65,Richmond,51.46131099999999,-0.303742
+65,"Brentford, County Court",51.4842409,-0.3043609
+65,"Great West Road, Ealing Road",51.4913803,-0.3039856
+65,Ealing Broadway,51.5136997,-0.3031306
+66,Romford Station,51.57472449999999,0.1826519
+66,Romford Market,51.5790739,0.1813886
+66,Marks Gate,51.5901971,0.1424532
+66,Newbury Park,51.5734779,0.08897669999999999
+66,Gants Hill,51.5767812,0.0661732
+66,Redbridge Station,51.5763264,0.0453986
+66,Wanstead,51.5767971,0.0249881
+66,Leytonstone,51.5649624,0.0088141
+67,Wood Green,51.5971722,-0.1098021
+67,Wood Green,51.5971722,-0.1098021
+67,"Green Lanes, West Green Road",51.5844105,-0.0764614
+67,West Green,51.586254,-0.0867628
+67,Stamford Hill,51.5686382,-0.0731048
+67,Stoke Newington,51.561175,-0.08349229999999999
+67,Stoke Newington,51.561175,-0.08349229999999999
+67,Dalston Junction,51.5459999,-0.0751485
+67,Dalston,51.54704,-0.06940349999999999
+67,Shoreditch,51.5229106,-0.0777472
+67,Aldgate,51.5133004,-0.0774081
+68,West Norwood,51.427905,-0.1002486
+68,Tulse Hill Station,51.43986,-0.10505
+68,Herne Hill,51.4609208,-0.0985404
+68,Herne Hill,51.4609208,-0.0985404
+68,Camberwell Green,51.4756016,-0.0928896
+68,Camberwell Green,51.4756016,-0.0928896
+68,Elephant & Castle,51.4938279,-0.0981368
+68,Waterloo,51.5041898,-0.1122489
+68,Waterloo,51.5041898,-0.1122489
+68,Aldwych,51.5130911,-0.1164802
+68,Holborn,51.5181143,-0.1104004
+68,Russell Square,51.521869,-0.1246032
+68,Euston,51.5282715,-0.1289675
+69,Walthamstow Central,51.5830128,-0.019886
+69,"Leyton, Bakers Arms",51.5749185,-0.013549
+69,"Leyton, Grange Park Road",51.56521830000001,-0.0136752
+69,"Leyton, Downsell Road",51.55316999999999,-0.0025209
+69,Stratford,51.5426313,-0.0010369
+69,Plaistow,51.5268317,0.0308143
+69,"Canning Town, Hermit Road",51.5209368,0.0125057
+69,Canning Town,51.5189494,0.0132
+70,"Chiswick, Business Park",51.4930604,-0.2748696
+70,"Acton, High Street",51.5068505,-0.2673267
+70,East Acton Lane,51.5123715,-0.2543317
+70,East Acton,51.5127758,-0.2476803
+70,North Pole Road,51.51923009999999,-0.2273689
+70,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+70,Chepstow Road,51.5170993,-0.1955316
+70,Chepstow Road,51.5170993,-0.1955316
+70,Queensway,51.51257870000001,-0.1873839
+70,Notting Hill Gate,51.5091772,-0.1961953
+70,Royal Albert Hall,51.5009088,-0.177366
+70,South Kensington,51.4953291,-0.1789909
+71,Chessington,51.363583,-0.296254
+71,Copt Gilders,51.35919000000001,-0.29498
+71,"Hook, Bridge Road",51.4682792,0.1849895
+71,Hook Junction,51.3748795,-0.3038393
+71,Surbiton,51.39400999999999,-0.302662
+71,Surbiton,51.39400999999999,-0.302662
+71,Kingston,51.41233,-0.300689
+72,East Acton,51.5127758,-0.2476803
+72,"Wood Lane, Du Cane Road",51.5181773,-0.2356671
+72,Shepherd's Bush,51.5051913,-0.22469
+72,Shepherd's Bush,51.5051913,-0.22469
+72,Brook Green,51.4960545,-0.2190422
+72,Hammersmith,51.491187,-0.223731
+72,Hammersmith,51.491187,-0.223731
+72,"Hammersmith Bridge, North Side",51.48972029999999,-0.2289675
+72,Castelnau,51.4803332,-0.2367515
+72,"Barnes, Red Lion",51.4755063,-0.2389859
+72,Barnes Common,51.4681254,-0.2413995
+72,Roehampton,51.4484339,-0.2397592
+72,"Roehampton, Bessborough Road",51.4463277,-0.2386829
+73,Victoria,51.4309209,-0.0936496
+73,"Park Lane, Hilton Hotel",51.5055096,-0.1503864
+73,Marble Arch,51.5133234,-0.1597734
+73,Oxford Circus,51.5163602,-0.1328952
+73,Oxford Circus,51.5163602,-0.1328952
+73,Tottenham Court Road,51.5185,-0.1321613
+73,Tottenham Court Road,51.5185,-0.1321613
+73,Warren Street,51.524438,-0.1385486
+73,Warren Street,51.524438,-0.1385486
+73,Euston,51.52894329999999,-0.1261751
+73,King's Cross,51.5347488,-0.1245845
+73,Islington Angel,51.5346761,-0.1042905
+73,Islington Green,51.5354865,-0.103688
+73,Mildmay Park,51.5499786,-0.084878
+73,Newington Green,51.5511621,-0.0858874
+73,Albion Road,51.554547,-0.08466159999999999
+73,Stoke Newington,51.561175,-0.08349229999999999
+74,"Putney, High Street",51.4642989,-0.2153882
+74,"Putney, High Street",51.4642989,-0.2153882
+74,Putney Bridge,51.459722,-0.1983352
+74,West Brompton,51.483494,-0.196802
+74,Earl's Court,51.490331,-0.1958417
+74,South Kensington,51.4953291,-0.1789909
+74,Hyde Park Corner,51.5029347,-0.1508562
+74,Marble Arch,51.5133234,-0.1597734
+74,Marble Arch,51.5133234,-0.1597734
+74,Portman Square,51.515381,-0.1546695
+74,Baker Street Station,51.4309209,-0.0936496
+75,Lewisham Station,51.46115090000001,-0.0073177
+75,"Catford, Town Centre",51.4453954,-0.0160913
+75,"Catford, Town Centre",51.4453954,-0.0160913
+75,"Catford, St. Dunstan's",51.4430327,-0.0237655
+75,Penge,51.41388490000001,-0.0570112
+75,Norwood Junction,51.39731,-0.07501000000000001
+75,West Croydon,51.3684193,-0.0998425
+75,Croydon Town Centre,51.3769529,-0.0956895
+76,Tottenham Hale Bus Station,51.58841109999999,-0.061242
+76,Tottenham Town Hall,51.5872187,-0.0725467
+76,Stamford Hill,51.56690570000001,-0.0726724
+76,Stoke Newington,51.561175,-0.08349229999999999
+76,"Hoxton, Baring Street",51.5366266,-0.0886478
+76,"Hoxton, Baring Street",51.5366266,-0.0886478
+76,Dalston Junction,51.5459999,-0.0751485
+76,Old Street Station,51.5256719,-0.0874922
+76,Mansion House,51.51300699999999,-0.08950899999999999
+76,Ludgate Circus,51.5141007,-0.1043311
+76,Aldwych,51.5130912,-0.1164853
+76,Waterloo,51.5043961,-0.1130969
+77,Waterloo,51.5040874,-0.1117601
+77,St Thomas' Hospital,51.4991539,-0.1188859
+77,Vauxhall,51.4309209,-0.0936496
+77,Lambeth College,51.4587037,-0.1410873
+77,Clapham Junction,51.4651737,-0.1708113
+77,Clapham Junction,51.4651737,-0.1708113
+77,"Garratt Lane, Wimbledon Road",51.4409636,-0.1869488
+77,Tooting Broadway,51.427867,-0.1678142
+77,Tooting Station,51.41986989999999,-0.16136
+78,Shoreditch,51.5229106,-0.0777472
+78,Shoreditch,51.5229106,-0.0777472
+78,Liverpool Street,51.5169907,-0.0810552
+78,Aldgate,51.5133004,-0.0774081
+78,"Tower Bridge Road, Druid Street",51.4997177,-0.0753387
+78,"Old Kent Road, Tesco",51.4854662,-0.0700918
+78,Peckham,51.47032369999999,-0.0673872
+78,Peckham Rye,51.4644631,-0.06657249999999999
+78,Nunhead,51.4657341,-0.054919
+79,"Alperton, Sainsbury's",51.5383862,-0.3028583
+79,Alperton,51.539601,-0.2988365
+79,Wembley Central,51.55214429999999,-0.2965274
+79,Wembley High Road,51.5531196,-0.295206
+79,"Preston Road, East Lane",51.5622614,-0.29827
+79,Preston Road Station,51.57197,-0.29508
+79,Kingsbury Circle,51.5853429,-0.2812115
+79,Queensbury,51.5942132,-0.2853683
+79,Canons Park,51.6076736,-0.2962361
+79,Edgware Station,51.6134923,-0.2753661
+80,"Belmont, High Down & Downview",51.4309209,-0.0936496
+80,Sutton Station,51.3614279,-0.193961
+80,"Sutton, Bus Garage",51.369469,-0.1985923
+80,Morden,51.394943,-0.19446
+80,Morden,51.394943,-0.19446
+80,St Helier,51.395985,-0.1875555
+80,"Hackbridge, Reynold's Close",51.3751002,-0.1556286
+81,Slough,51.4309209,-0.0936496
+81,Langley Fire Station,51.4309209,-0.0936496
+81,Colnbrook,51.4973363,-0.1045651
+81,Poyle,51.4754669,-0.5118773000000001
+81,"Bath Road, Hatch Lane",51.486421,-0.4760167
+81,"Bath Road, Sipson Road",51.5003514,-0.4640708
+81,"Bath Road, Nobel Drive",51.4815821,-0.4302396
+81,Cranford,51.4720623,-0.4055896
+81,Hounslow West,51.469435,-0.3837709
+81,"Hounslow, Bell Corner",51.468569,-0.3666325
+81,"Hounslow, Bus Station",51.4708688,-0.3546457
+83,Golders Green,51.5740013,-0.1987725
+83,"Hendon, Queens Road",51.5841638,-0.2202724
+83,West Hendon Broadway,51.5752931,-0.2378247
+83,Kingsbury Green,51.5814409,-0.2619577
+83,Wembley Arena,51.558096,-0.282586
+83,Wembley Stadium,51.55602469999999,-0.2796177
+83,Alperton,51.539601,-0.2988365
+83,Alperton,51.539601,-0.2988365
+85,Kingston,51.41233,-0.300689
+85,Kingston,51.41233,-0.300689
+85,"Kingston Hill, Queens Road",51.4171617,-0.2825256
+85,Roehampton Vale,51.439021,-0.2484373
+85,Roehampton,51.4584564,-0.2425687
+85,Roehampton Vale,51.439021,-0.2484373
+85,Putney Heath,51.4524424,-0.2298485
+85,Putney Bridge,51.46112900000001,-0.2034236
+86,Stratford,51.5426313,-0.0010369
+86,"Woodgrange Park, Katherine Road",51.5346001,0.0467122
+86,Manor Park,51.4543709,-0.0001943
+86,Ilford Broadway,51.556619,0.076251
+86,Ilford Hill,51.5586041,0.07009270000000001
+86,Ilford,51.556619,0.076251
+86,Chadwell Heath,51.5722283,0.141995
+86,"Romford, North Street",51.5805763,0.1780317
+86,Romford Market,51.5790739,0.1813886
+86,Romford Station,51.57472449999999,0.1826519
+87,Wandsworth,51.45837299999999,-0.1891356
+87,Wandsworth,51.45837299999999,-0.1891356
+87,Stockwell,51.4689424,-0.1194031
+87,Vauxhall,51.4309209,-0.0936496
+87,Lambeth Bridge,51.4945633,-0.123211
+87,Parliament Square,51.5007668,-0.1261294
+87,"Whitehall, Horse Guards",51.5041686,-0.1258204
+87,Trafalgar Square,51.508039,-0.128069
+87,Aldwych,51.5130914,-0.1164923
+88,Camden Town,51.5390261,-0.1425516
+88,Mornington Crescent,51.4794391,-0.4063284
+88,Warren Street,51.5244002,-0.1383538
+88,Oxford Circus,51.5161415,-0.1334985
+88,"Whitehall, Horse Guards",51.5049111,-0.1273704
+88,Parliament Square,51.5007668,-0.1261294
+88,Vauxhall,51.4877795,-0.1169126
+88,Stockwell,51.4690257,-0.1195636
+88,Clapham Common,51.4589252,-0.1493071
+89,Lewisham Station,51.4652098,-0.0131213
+89,Blackheath Village,51.4652738,0.0094822
+89,"Shooters Hill Road, Sun-in-the-Sands",51.4746479,0.022129
+89,"Blackheath, Royal Standard",51.4779946,0.0202001
+89,"Shooters Hill, Eaglesfield Road",51.4689548,0.07025769999999999
+89,Welling Corner,51.4626258,0.1081541
+89,Welling Corner,51.4626258,0.1081541
+89,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+89,"Bexleyheath, Bus Garage",51.45334099999999,0.13822
+89,"Northend Road, Thames Road",51.4872325,-0.2844694
+89,Slade Green,51.4695282,0.1928854
+90,Northolt,51.546615,-0.373103
+90,"Yeading, White Hart",51.4675324,-0.2541425
+90,"Hayes End, Lansbury Drive",51.5258519,-0.4193931
+90,Hayes End,51.5257,-0.4357732
+90,Hayes & Harlington Station,51.5029848,-0.4203779
+90,Harlington Corner,51.4809415,-0.434335
+90,Hatton Cross,51.4651031,-0.4157165
+90,Feltham,51.44414800000001,-0.410772
+91,Crouch End,51.5819979,-0.1221464
+91,Hornsey Rise,51.57271290000001,-0.1261329
+91,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+91,King's Cross,51.5347488,-0.1245845
+91,Euston,51.5287996,-0.1265979
+91,Russell Square,51.5220614,-0.127641
+91,Aldwych,51.513388,-0.1154888
+91,Trafalgar Square,51.508039,-0.128069
+91,Trafalgar Square,51.508039,-0.128069
+92,Ealing Hospital,51.5075205,-0.3465216
+92,"Greenford, Iron Bridge",51.50977899999999,-0.357687
+92,Greenford Broadway,51.5283954,-0.3553102
+92,Greenford Station,51.5423355,-0.3463373
+92,Sudbury Town,51.5503085,-0.316207
+92,Wembley Central,51.55214429999999,-0.2965274
+92,Wembley Stadium,51.55602469999999,-0.2796177
+92,Wembley Trading Estate,51.550501,-0.3048409
+92,Brent Park,51.5742449,-0.2287648
+92,St Raphael's North,51.55207859999999,-0.2622574
+93,North Cheam,51.3619271,-0.2189255
+93,"Sutton Common Road, Woodstock",51.3795675,-0.2014588
+93,Morden,51.3984637,-0.1763977
+93,Morden,51.3984637,-0.1763977
+93,Wimbledon,51.41833889999999,-0.2206288
+93,Wimbledon Village,51.41833889999999,-0.2206288
+93,Wimbledon,51.41833889999999,-0.2206288
+93,Putney Heath,51.4524424,-0.2298485
+93,Putney Station,51.4611807,-0.2164913
+93,Putney Bridge,51.46118999999999,-0.2037456
+94,Acton Green,51.5030641,-0.2663253
+94,Acton Green,51.5030641,-0.2663253
+94,Goldhawk Road Station,51.5018056,-0.2264944
+94,Shepherd's Bush,51.5051913,-0.22469
+94,Notting Hill Gate,51.5091315,-0.197414
+94,Lancaster Gate,51.5112845,-0.1804758
+94,Marble Arch,51.5133234,-0.1597734
+94,Portman Square,51.515381,-0.1546695
+94,Oxford Circus,51.5159378,-0.1342798
+94,Piccadilly Circus,51.5059249,-0.1454693
+95,"Southall, Town Hall",51.5113272,-0.3751471
+95,Greenford Broadway,51.52833769999999,-0.3562134
+95,"Perivale, Central Parade",51.5847721,-0.3324285
+95,Hanger Lane Station,51.530061,-0.2929893000000001
+95,"North Acton, Gipsy Corner",51.5219526,-0.2580821
+95,"East Acton, Savoy Circus",51.5140035,-0.247772
+95,Shepherd's Bush,51.5051913,-0.22469
+96,Bluewater,51.4309209,-0.0936496
+96,Dartford,51.44621,0.216872
+96,Crayford,51.4501131,0.1822046
+96,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+96,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+96,Welling Corner,51.4626258,0.1081541
+96,Plumstead Station,51.4896774,0.0847463
+96,"Plumstead, Lakedale Road",51.4845804,0.09086029999999999
+96,Woolwich Market,51.4894752,0.06758829999999999
+96,Woolwich,51.4894752,0.06758829999999999
+97,Chingford Station,51.6320667,0.007362700000000001
+97,Chingford Mount,51.6113592,-0.0180674
+97,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+97,Walthamstow Central,51.5830128,-0.019886
+97,Leyton Green,51.5754944,-0.0083377
+97,"Leyton, Grange Park Road",51.5658352,-0.0144275
+97,"Leyton, Downsell Road",51.553328,-0.0016243
+97,Stratford City,51.5440354,-0.0053088
+98,"Willesden, Bus Garage",51.5476301,-0.2369246
+98,"Willesden Lane, Coverdale Road",51.5441689,-0.2143084
+98,Kilburn High Road Station,51.537243,-0.192318
+98,Edgware Road Station,51.51988249999999,-0.1678336
+98,Marble Arch,51.5133234,-0.1597734
+98,Marble Arch,51.5133234,-0.1597734
+98,Portman Square,51.515381,-0.1546695
+98,Oxford Circus,51.51587929999999,-0.1356139
+98,Holborn,51.518113,-0.1103907
+99,Woolwich,51.4602922,0.1464941
+99,Plumstead Bus Garage,51.4913502,0.084419
+99,"Plumstead, Lakedale Road",51.4852476,0.0912847
+99,Upper Belvedere,51.4309209,-0.0936496
+99,Erith,51.480818,0.174675
+99,Slade Green,51.4695282,0.1928854
+99,Northend Road,51.4694963,0.1812364
+99,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+100,"London Wall, Museum of London",51.5176183,-0.0967782
+100,Liverpool Street,51.517791,-0.0837724
+100,Aldgate,51.5135207,-0.0768032
+100,Aldgate,51.5135207,-0.0768032
+100,Tower Gateway,51.5106312,-0.0737553
+100,Wapping,51.5041774,-0.0563736
+100,Shadwell,51.53525819999999,-0.3737537
+101,Wanstead,51.5767971,0.0249881
+101,Aldersbrook,51.5582903,0.0432123
+101,Manor Park,51.4536631,0.0027204
+101,East Ham Station,51.5393698,0.0510659
+101,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+101,"East Ham, Central Park",51.5293175,0.0527634
+101,"East Ham, Ron Leighton Way",51.53700509999999,0.0515097
+101,Beckton Alps,51.5192628,0.0612645
+101,Beckton Station,51.5144016,0.06153319999999999
+101,Cyprus,51.5306764,-0.0486561
+101,Gallions Reach Station,51.5090228,0.07172769999999999
+101,"Gallions Reach, Shopping Park",51.4309209,-0.0936496
+102,Edmonton Green,51.6248126,-0.0581806
+102,North Middlesex Hospital,51.6131618,-0.0735832
+102,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+102,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+102,"Palmers Green, North Circular Road",51.6122666,-0.1091537
+102,Muswell Hill,51.5911816,-0.1443015
+102,East Finchley,51.592468,-0.1664342
+102,Henley's Corner,51.4309209,-0.0936496
+102,Golders Green,51.5740013,-0.1987725
+102,Golders Green,51.5740013,-0.1987725
+102,"Cricklewood, Pennine Drive",51.5658262,-0.2141234
+102,Brent Cross,51.5763589,-0.2236956
+103,Chase Cross,51.60164,0.17854
+103,"Romford, Parkside Avenue",51.5884474,0.1770259
+103,Romford North Street Bus Garage,51.5823836,0.1761951
+103,Romford Market,51.5790739,0.1813886
+103,Romford Station,51.57472449999999,0.1826519
+103,Becontree Heath,51.5609465,0.1488995
+103,Dagenham East,51.5402631,0.1482103
+103,"South Hornchurch, Newtons Corner",51.53084699999999,0.1871649
+103,Rainham Interchange,51.5168805,0.1911589
+104,Stratford,51.5339854,0.0168531
+104,Upton Park Station,51.5353424,0.0352766
+104,"Upton Park, Boleyn",51.5305005,0.0384915
+104,"East Ham, Ron Leighton Way",51.5370071,0.05151679999999999
+104,Beckton Alps,51.5192628,0.0612645
+104,"East Ham, Central Park",51.5293175,0.0527634
+104,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+104,East Ham Station,51.5393698,0.0510659
+104,Manor Park,51.4540626,0.0005865
+105,Greenford Station,51.5423355,-0.3463373
+105,Greenford Broadway,51.52833769999999,-0.3562134
+105,"Southall, Town Hall",51.5113272,-0.3751471
+105,"Southall, Brent Road",51.5007727,-0.3997526
+105,Cranford,51.4870278,-0.4320017
+105,Harlington Corner,51.4809415,-0.434335
+105,"Bath Road, Sipson Road",51.4989643,-0.4629989
+105,Heathrow Central,51.4724711,-0.4544586
+106,Finsbury Park Station,51.5646425,-0.1058553
+106,Stoke Newington,51.5540035,-0.0748071
+106,Stoke Newington,51.5540035,-0.0748071
+106,Clapton Pond,51.5561061,-0.05490830000000001
+106,Hackney Well Street,51.5409953,-0.04943699999999999
+106,Ash Grove,51.481438,-0.3919584
+106,Ash Grove,51.481438,-0.3919584
+106,Whitechapel,51.518398,-0.0628557
+107,Edgware,51.61548819999999,-0.2609598
+107,Borehamwood Station,51.657728,-0.272308
+107,"Borehamwood, Tesco",51.4309209,-0.0936496
+107,"Borehamwood, Warwick Road",51.49182570000001,-0.1990845
+107,Stirling Corner,51.643381,-0.2551272
+107,"Barnet, Arkley Hotel",51.6522231,-0.2204527
+107,"Barnet, Odeon",51.64663059999999,-0.1865655
+107,New Barnet,51.649276,-0.176187
+108,Stratford International Bus Station,51.5453665,-0.0099022
+108,Bow Church,51.5287753,-0.0167013
+108,"Poplar, All Saints",51.5105521,-0.0118612
+108,Canning Town,51.5189494,0.0132
+108,North Greenwich,51.4859576,0.007494900000000001
+108,East Greenwich,51.4309209,-0.0936496
+108,"Blackheath, Royal Standard",51.4779946,0.0202001
+108,Blackheath Village,51.4652738,0.0094822
+108,Lewisham Station,51.4652098,-0.0131213
+109,Croydon Town Centre,51.3769529,-0.0956895
+109,West Croydon,51.3684193,-0.0998425
+109,Thornton Heath Pond,51.39415080000001,-0.1149765
+109,Norbury,51.4086775,-0.1167542
+109,"Streatham, Green Lane",51.4118582,-0.1104441
+109,Streatham Station,51.4259857,-0.131308
+109,Streatham Hill Station,51.4382009,-0.1270706
+109,Brixton,51.4533088,-0.1205905
+110,Hounslow Bus Station,51.4708688,-0.3546457
+110,Hospital Bridge Roundabout,51.44267,-0.3652385
+110,Twickenham,51.4453043,-0.3375429
+110,Twickenham,51.4453043,-0.3375429
+110,West Middlesex Hospital,51.4734184,-0.3244425
+111,Kingston,51.41233,-0.300689
+111,Hampton Wick,51.413541,-0.321331
+111,Hampton Court Roundabout,51.4051753,-0.3417169
+111,Hampton Station,51.4158208,-0.3719119
+111,Hampton Station,51.4158208,-0.3719119
+111,"Hanworth, Main Street",51.4489479,-0.3829269
+111,"Hounslow, Bus Station",51.4708688,-0.3546457
+111,Heston,51.4309209,-0.0936496
+111,Cranford,51.486932,-0.4318624
+111,"Bath Road, Nobel Drive",51.4815821,-0.4302396
+111,"Bath Road, Sipson Road",51.4989341,-0.4618918
+111,Heathrow Central,51.4724711,-0.4544586
+112,Ealing Broadway,51.5135109,-0.3036571
+112,Hanger Lane Station,51.530061,-0.2929893000000001
+112,Stonebridge Park,51.5456178,-0.2617279
+112,Neasden Junction,51.5626819,-0.2536987
+112,Brent Cross,51.5763589,-0.2236956
+113,Edgware,51.5163626,-0.1651413
+113,Apex Corner,51.4369075,-0.3784005
+113,Hendon Central,51.583202,-0.226399
+113,Hendon Central,51.583202,-0.226399
+113,Finchley Road & Frognal,51.5585086,-0.1818591
+113,Swiss Cottage,51.5425872,-0.1724737
+113,Baker Street Station,51.5231548,-0.156863
+113,Baker Street Station,51.5231548,-0.156863
+113,Portman Square,51.515381,-0.1546695
+113,Portman Square,51.515381,-0.1546695
+113,Marble Arch,51.5133234,-0.1597734
+113,Oxford Circus,51.5158971,-0.1352142
+114,Mill Hill Broadway,51.6133816,-0.2463566
+114,Burnt Oak,51.602809,-0.266965
+114,Queensbury,51.5942132,-0.2853683
+114,"Kenton, Library",51.59262649999999,-0.3111454
+114,Harrow,51.580559,-0.341995
+114,South Harrow,51.5683717,-0.3553483
+114,"Field End Road, Victoria Road",51.5696578,-0.3900522
+114,"South Ruislip, Ruislip Manor",51.55507919999999,-0.399575
+114,Ruislip,51.5758719,-0.421236
+115,"East Ham, Central Park",51.5293175,0.0527634
+115,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+115,"Upton Park, Boleyn",51.5305005,0.0384915
+115,"Plaistow, Balaam street",51.5260131,0.0238468
+115,"Canning Town, Barking Road",51.5175196,0.0115068
+115,Canning Town,51.5189494,0.0132
+115,"Poplar, All Saints",51.5105521,-0.0118612
+115,"Limehouse, Burdett Road",51.5209123,-0.0327503
+115,"Stepney, Arbour Square",51.5140186,-0.0481747
+115,"Stepney, Arbour Square",51.5140186,-0.0481747
+115,Aldgate,51.5135207,-0.0768032
+116,Ashford Hospital,51.4309209,-0.0936496
+116,Bedfont Green,51.45109910000001,-0.4402292
+116,Hounslow Heath,51.4563954,-0.3849625
+116,"Hounslow, Bell Corner",51.468569,-0.3666325
+116,"Hounslow, Bus Station",51.46092179999999,-0.373149
+117,West Middlesex Hospital,51.4734184,-0.3244425
+117,Isleworth,51.467121,-0.329003
+117,Hounslow Heath,51.4563954,-0.3849625
+117,Hounslow,51.46092179999999,-0.373149
+117,Lower Feltham,51.436601,-0.426105
+117,Ashford,51.4309209,-0.0936496
+117,Fordbridge Park,51.4269571,-0.4764696
+117,Staines,51.45742550000001,-0.4085313
+118,Brixton,51.4612794,-0.1156148
+118,Brixton,51.4612794,-0.1156148
+118,"Streatham Hill, Christchurch Road",51.4402956,-0.1089125
+118,Streatham Hill Station,51.4307467,-0.1294977
+118,"Streatham, St Leonard's Church",51.42926610000001,-0.1311095
+118,Streatham,51.4307467,-0.1294977
+118,"Rowan Road, Manor Road",51.407602,-0.1415332
+118,"Rowan Road, Manor Road",51.407602,-0.1415332
+118,Mitcham,51.4242858,-0.1420112
+118,Mitcham,51.4242858,-0.1420112
+118,Morden,51.394943,-0.19446
+119,Bromley North,51.406025,0.013156
+119,Bromley South,51.406025,0.013156
+119,Hayes Station,51.37633599999999,0.010589
+119,Shirley,51.3784662,-0.0616112
+119,Shirley Inn,51.3744006,-0.05023610000000001
+119,"Addiscombe Road, Shirley Road",51.3750364,-0.0761587
+119,East Croydon,51.3769529,-0.0956895
+119,"South Croydon, South End",51.3639044,-0.0980944
+119,"Purley Way, Colonnades",51.3563828,-0.1135816
+120,Hounslow Bus Station,51.46092179999999,-0.373149
+120,"Hounslow, Bell Corner",51.468569,-0.3666325
+120,Lampton Corner,51.4309209,-0.0936496
+120,Norwood Green,51.4966737,-0.3743679
+120,"Southall, The Green",51.5023286,-0.3821557
+120,"Southall, Town Hall",51.5113272,-0.3751471
+120,"Lady Margaret Road, Ruislip Rd",51.5220189,-0.3747392
+120,"Yeading, White Hart",51.4668898,-0.2535508
+120,"Northolt, Western Avenue",51.5152423,-0.2565013
+120,Northolt,51.546615,-0.373103
+121,Enfield Island Village,51.66612199999999,-0.015382
+121,Enfield Lock Station,51.6708436,-0.0284106
+121,Enfield Highway,51.652918,-0.041145
+121,Ponders End Bus Garage,51.6452225,-0.04863729999999999
+121,Enfield,51.6532423,-0.1162248
+121,Oakwood,51.4996676,-0.2061929
+121,Southgate,51.5423535,-0.08493669999999999
+121,Palmers Green,51.6214872,-0.1075657
+121,"Palmers Green, North Circular Road",51.6122666,-0.1091537
+121,Wood Green,51.5971722,-0.1098021
+121,Turnpike Lane Station,51.5904278,-0.1027587
+122,Plumstead Bus Garage,51.4913502,0.084419
+122,Woolwich,51.4839216,0.1383058
+122,Woolwich,51.4839216,0.1383058
+122,Well Hall Roundabout,51.4549092,0.0512893
+122,Eltham Green,51.4533383,0.0356381
+122,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+122,Brockley Rise,51.4492257,-0.0392146
+122,Forest Hill,51.4513909,-0.0593561
+122,Sydenham,51.3816463,-0.0940886
+122,Crystal Palace,51.45665589999999,-0.07155589999999999
+123,Wood Green,51.5971722,-0.1098021
+123,Turnpike Lane Station,51.5904278,-0.1027587
+123,Lordship Lane,51.4569725,-0.07542599999999999
+123,"Tottenham, Town Hall",51.5872187,-0.0725467
+123,Tottenham Hale Station,51.5890318,-0.05979599999999999
+123,"Walthamstow, Beacontree Avenue",51.5977897,0.0033351
+123,"Walthamstow, Beacontree Avenue",51.5977897,0.0033351
+123,Waterworks Corner,51.5961326,0.0104878
+123,Charlie Brown's Roundabout,51.5934938,0.0370989
+123,Charlie Brown's Roundabout,51.5934938,0.0370989
+123,Gants Hill,51.5791987,0.0640264
+123,Ilford,51.5546614,0.07253409999999999
+124,"Catford, St Dunstan's College",51.4434815,-0.0283657
+124,"Catford, Town Centre",51.4453954,-0.0160913
+124,"Downham, Shroffold Road",51.425638,0.0015921
+124,Grove Park,51.5922603,-0.2588401
+124,"Dunkery Road, Mottingham Road",51.4297244,0.0420724
+124,Mottingham,51.4342505,0.0468761
+124,Eltham Church,51.4506338,0.0570862
+124,"Eltham, Southend Crescent",51.44825729999999,0.0632853
+125,Winchmore Hill,51.6320279,-0.09580219999999999
+125,Eversley Park Road,51.64383729999999,-0.109846
+125,Southgate,51.5424973,-0.0848603
+125,Hampden Square,51.6323276,-0.1417747
+125,Whetstone,51.6300102,-0.1747954
+125,North Finchley,51.6135087,-0.1754198
+125,Finchley Central,51.601633,-0.193361
+126,Bromley Town Centre,51.406025,0.013156
+126,Bromley North,51.406025,0.013156
+126,Plaistow Green,51.4139535,0.0168425
+126,Plaistow Green,51.4139535,0.0168425
+126,Grove Park,51.4329249,0.021203
+126,Mottingham,51.4368565,0.0431531
+126,"Eltham, High Street",51.450685,0.0533581
+127,Purley,51.339228,-0.119711
+127,Woodcote Green,51.3479553,-0.1474798
+127,Wallington,51.363978,-0.151845
+127,Wallington,51.363978,-0.151845
+127,Wrythe Green,51.37563979999999,-0.1775913
+127,Hackbridge Corner,51.379288,-0.156685
+127,Mitcham,51.4234696,-0.1422232
+127,Mitcham,51.4234696,-0.1422232
+127,Tooting Broadway,51.427867,-0.1678142
+128,Romford Station,51.577076,0.178319
+128,"Romford, The Brewery",51.5757212,0.1798406
+128,Romford Market,51.5790739,0.1813886
+128,Romford Queens Hospital,51.5688117,0.1807796
+128,Becontree Heath,51.5609465,0.1488995
+128,Bennett's Castle Lane,51.5566204,0.1274857
+128,Bennett's Castle Lane,51.5566204,0.1274857
+128,"Goodmayes, Mayfield Road",51.564386,0.1293136
+128,Ilford,51.55345459999999,0.0728955
+128,Ilford,51.55345459999999,0.0728955
+128,Gants Hill,51.58065879999999,0.0672369
+128,"Barkingside, Tesco",51.58605319999999,0.08191999999999999
+128,"Barkingside, Fullwell Cross",51.59451199999999,0.08571999999999999
+128,Claybury Broadway,51.5886482,0.0519222
+129,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+129,East Greenwich,51.4309209,-0.0936496
+129,East Greenwich,51.4309209,-0.0936496
+129,North Greenwich,51.4859576,0.007494900000000001
+130,New Addington,51.348184,-0.017094
+130,Addington Village,51.3587133,-0.0303994
+130,Shirley Park,51.3811242,-0.0613737
+130,Norwood Junction,51.39731,-0.07501000000000001
+130,"Thornton Heath, Parchmore Road",51.4044757,-0.1019415
+131,Kingston,51.41233,-0.300689
+131,"New Malden, Foundation Roundabout",51.40066299999999,-0.259263
+131,"New Malden, Fountain Roundabout",51.3978781,-0.2554973
+131,Shannon Corner,51.3993558,-0.2429132
+131,Raynes Park,51.4084257,-0.2298751
+131,Wimbledon,51.41833889999999,-0.2206288
+131,Wimbledon,51.41833889999999,-0.2206288
+131,Colliers Wood,51.41704439999999,-0.1778555
+131,Tooting Broadway,51.427867,-0.1678142
+132,North Greenwich,51.4859576,0.007494900000000001
+132,East Greenwich,51.4309209,-0.0936496
+132,"Shooters Hill Road, Sun-in-the-Sands",51.4751267,0.0286902
+132,Eltham Station,51.45564,0.0525
+132,Eltham,51.4506338,0.0570862
+132,Blendon,51.44793379999999,0.1220942
+132,Bexley,51.439933,0.154327
+132,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+133,Streatham Station,51.4259857,-0.131308
+133,Streatham Hill Station,51.4382009,-0.1270706
+133,"Streatham Hill, Telford Avenue",51.4419108,-0.1355643
+133,Brixton,51.4533088,-0.1205905
+133,Brixton,51.4533088,-0.1205905
+133,Kennington Church,51.5074444,-0.1949528
+133,Elephant & Castle,51.4939906,-0.1005164
+133,London Bridge,51.5086048,-0.0875601
+133,Monument,51.50999,-0.0855373
+133,Liverpool Street,51.5151887,-0.07828249999999999
+134,North Finchley,51.6135087,-0.1754198
+134,Friern Barnet,51.6212348,-0.1632817
+134,Muswell Hill,51.5910045,-0.1411939
+134,Muswell Hill,51.5910045,-0.1411939
+134,Archway,51.5714491,-0.1388138
+134,Kentish Town,51.546046,-0.1415843
+134,Camden Town,51.5390261,-0.1425516
+134,Camden Town,51.5390261,-0.1425516
+134,Mornington Crescent,51.5344237,-0.1393683
+134,Warren Street,51.5244002,-0.1383538
+134,Tottenham Court Road Station,51.5162811,-0.1300406
+135,Crossharbour,51.4974839,-0.0151232
+135,Canary Wharf,51.5054306,-0.0235333
+135,"Limehouse, Burdett Road",51.5205334,-0.0320335
+135,"Stepney, Arbour Square",51.5140186,-0.0481747
+135,Aldgate,51.5135207,-0.0768032
+135,Liverpool Street,51.5174995,-0.08269399999999999
+135,Old Street Station,51.5256719,-0.0874922
+136,Grove Park,51.4329249,0.021203
+136,"Downham, Bromley Road",51.4369124,-0.0185613
+136,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+136,"Catford, Town Centre",51.4453954,-0.0160913
+136,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+136,New Cross,51.4769047,-0.0336897
+136,New Cross Gate,51.4749904,-0.0403466
+136,Peckham,51.47032369999999,-0.0673872
+136,Elephant & Castle,51.4938279,-0.0981368
+137,"Streatham Hill, Telford Avenue",51.4419108,-0.1355643
+137,Clapham Common,51.4762752,-0.1179147
+137,Clapham Park,51.459505,-0.1335192
+137,Queenstown Road Station,51.4749596,-0.1466578
+137,Battersea Park Station,51.47696,-0.14751
+137,Sloane Square,51.49299509999999,-0.1564588
+137,Sloane Square,51.49299509999999,-0.1564588
+137,Hyde Park Corner,51.5029347,-0.1508562
+137,Marble Arch,51.5133234,-0.1597734
+137,Oxford Circus,51.5157462,-0.1363802
+138,Bromley North,51.406025,0.013156
+138,Hayes Station,51.37633599999999,0.010589
+138,Coney Hall,51.3711435,-0.0014082
+139,Golders Green,51.5746226,-0.2025805
+139,"Finchley Road, Hendon Way",51.5680875,-0.2078815
+139,Baker Street Station,51.5231548,-0.156863
+139,Baker Street Station,51.5231548,-0.156863
+139,Portman Square,51.515381,-0.1546695
+139,Oxford Circus,51.51576240000001,-0.1364384
+139,Piccadilly Circus,51.50384099999999,-0.1495126
+139,Piccadilly Circus,51.50384099999999,-0.1495126
+139,Trafalgar Square,51.4881349,-0.0895747
+139,Aldwych,51.5116273,-0.1189037
+139,Waterloo,51.501682,-0.1088358
+140,Heathrow Central,51.4724711,-0.4544586
+140,"Bath Road, Sipson Road",51.4977762,-0.4624348
+140,Harlington Corner,51.4809415,-0.434335
+140,Hayes & Harlington Station,51.5029848,-0.4203779
+140,"Yeading, Willow Tree Lane",51.5291787,-0.3981875
+140,"Yeading, White Hart",51.4665681,-0.2534512
+140,"Northolt, Target Roundabout",51.5433066,-0.3777375
+140,Northolt,51.546615,-0.373103
+140,South Harrow,51.5683717,-0.3553483
+140,Harrow,51.580559,-0.341995
+140,Harrow & Wealdstone Station,51.59172359999999,-0.3343587
+140,Harrow Weald,51.6052581,-0.3380395
+141,"Palmers Green, North Circular Road",51.6122666,-0.1091537
+141,Wood Green,51.5971722,-0.1098021
+141,Wood Green,51.5971722,-0.1098021
+141,Turnpike Lane Station,51.5904278,-0.1027587
+141,"Harringay, Salisbury Road",51.5814632,-0.0989471
+141,"Green Lanes, Gloucester Drive",51.5670684,-0.0945309
+141,Newington Green,51.5511621,-0.0858874
+141,"Hoxton, Baring Street",51.5366266,-0.0886478
+141,Old Street Station,51.5256719,-0.0874922
+141,"Moorgate, Finsbury Circus",51.5185065,-0.0883728
+141,Mansion House,51.51300699999999,-0.08950899999999999
+141,London Bridge,51.5086048,-0.0875601
+142,Watford Junction,51.66112829999999,-0.3970199
+142,Bushey Station,51.4309209,-0.0936496
+142,Bushey Heath,51.640213,-0.344442
+142,Stanmore Station,51.6196885,-0.3031205
+142,Edgware,51.61548819999999,-0.2609598
+142,Burnt Oak,51.602809,-0.266965
+142,"Colindale, Superstores",51.5942575,-0.2607018
+142,West Hendon Broadway,51.5756924,-0.2375372
+142,Brent Cross,51.5763589,-0.2236956
+143,Brent Cross,51.5763589,-0.2236956
+143,Hendon Central,51.583202,-0.226399
+143,"Finchley, Church End",51.604606,-0.1882833
+143,East Finchley Schools,51.592468,-0.1664342
+143,East Finchley,51.592468,-0.1664342
+143,East Finchley,51.592468,-0.1664342
+143,Highgate Village,51.556431,-0.1463122
+143,Archway,51.5723646,-0.1402196
+144,Muswell Hill,51.5910059,-0.1411991
+144,"Alexandra Park, Park Road",51.5990742,-0.1335391
+144,Hornsey,51.57350109999999,-0.1302347
+144,Turnpike Lane Station,51.5904278,-0.1027587
+144,Wood Green,51.5971722,-0.1098021
+144,Wood Green,51.5971722,-0.1098021
+144,"Lordship Lane, Downhills Way",51.5958467,-0.0910619
+144,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+144,Edmonton,51.6241533,-0.0603899
+144,Edmonton Green,51.6248126,-0.0581806
+145,"Dagenham, Asda",51.5299749,0.1425747
+145,"Dagenham, New Road",51.5285492,0.1564976
+145,Dagenham Village,51.5362298,0.1408327
+145,"Becontree, Martins Corner",51.5625977,0.1224296
+145,Fair Cross,51.5435767,0.0795854
+145,Ilford,51.5539678,0.073196
+145,Redbridge Station,51.5763264,0.0453986
+145,Wanstead Station,51.5756323,0.0287819
+145,Leytonstone,51.5493318,0.0049165
+146,Bromley North,51.406025,0.013156
+146,Bromley South,51.406025,0.013156
+146,Downe,51.3286548,0.0553793
+147,Ilford,51.5539372,0.0732529
+147,Ilford Broadway,51.556619,0.076251
+147,"Little Ilford Lane, Romford Road",51.55046249999999,0.059298
+147,East Ham Station,51.5393698,0.0510659
+147,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+147,"Upton Park, Boleyn",51.5305005,0.0384915
+147,Prince Regent,51.5178274,0.0321034
+147,Canning Town,51.5189494,0.0132
+148,Camberwell Green,51.4756016,-0.0928896
+148,Elephant & Castle,51.4938058,-0.0977932
+148,Parliament Square,51.5010421,-0.1268514
+148,Victoria,51.4309209,-0.0936496
+148,Hyde Park Corner,51.5029347,-0.1508562
+148,Marble Arch,51.5132225,-0.1588937
+148,Lancaster Gate,51.5117363,-0.1777176
+148,Notting Hill Gate,51.5086865,-0.1995831
+148,Holland Park Roundabout,51.5042925,-0.217039
+148,Shepherd's Bush,51.5051913,-0.22469
+148,White City,51.51146199999999,-0.2376332
+148,White City,51.51146199999999,-0.2376332
+149,Edmonton Green,51.6248126,-0.0581806
+149,"Snells Park, Sainsburys",51.609054,-0.0691713
+149,"Tottenham, Town Hall",51.5872187,-0.0725467
+149,"Tottenham, Town Hall",51.5872187,-0.0725467
+149,Stamford Hill,51.57418759999999,-0.0729267
+149,Stoke Newington,51.5568488,-0.0748084
+149,"Dalston, Downham Road",51.5394245,-0.0870648
+149,Shoreditch,51.5256391,-0.07789499999999999
+149,Monument,51.50999,-0.0855373
+149,London Bridge,51.5086048,-0.0875601
+150,Becontree Heath,51.5609465,0.1488995
+150,Bennett's Castle Lane,51.5559895,0.127183
+150,"Goodmayes, Mayfield Road",51.564386,0.1293136
+150,"Ilford, High Road",51.55918,0.0747613
+150,Ilford Broadway,51.556619,0.076251
+150,Gants Hill,51.5804109,0.0663594
+150,"Barkingside, Fullwell Cross",51.59451199999999,0.08571999999999999
+150,"Barkingside, Tesco",51.58605319999999,0.08191999999999999
+150,"Hainault, The Lowe",51.6128423,0.1079703
+150,Chigwell Row,51.50930289999999,-0.0601111
+151,Wallington,51.5310335,0.0585672
+151,Wallington,51.5310335,0.0585672
+151,Hackbridge,51.3751002,-0.1556286
+151,Wrythe Green,51.3766213,-0.1780055
+151,"St Helier, Rose Hill",51.39381479999999,-0.1871983
+151,"Sutton, Bushey Road",51.3686485,-0.1992887
+151,"Sutton, Bushey Road",51.3686485,-0.1992887
+151,Sutton Town Centre,51.3614279,-0.193961
+151,Cheam,51.3592217,-0.2091238
+151,North Cheam,51.3619271,-0.2189255
+151,Worcester Park,51.38029,-0.24468
+152,Pollards Hill,51.4000406,-0.1332582
+152,Eastfields,51.4627155,-0.1967312
+152,Colliers Wood,51.41704439999999,-0.1778555
+152,Colliers Wood,51.41704439999999,-0.1778555
+152,Raynes Park,51.4084257,-0.2298751
+152,Raynes Park High School,51.4032764,-0.2394806
+152,Raynes Park High School,51.4032764,-0.2394806
+152,"New Malden, Fountain Roundabout",51.3978781,-0.2554973
+153,Finsbury Park Station,51.5646425,-0.1058553
+153,"Holloway, Nags Head",51.55724250000001,-0.1204364
+153,"Barnsbury, Offord Road",51.5441596,-0.1096795
+153,Islington Angel,51.5346761,-0.1042905
+153,Islington Angel,51.5346761,-0.1042905
+153,Barbican,51.5202077,-0.09378639999999999
+153,"Moorgate, Finsbury Square",51.5188228,-0.08795879999999999
+154,West Croydon,51.368451,-0.09966350000000002
+154,Croydon Town Centre,51.3769529,-0.0956895
+154,"Stafford Road, The Chase",51.3596298,-0.1389609
+154,Wallington,51.363978,-0.151845
+154,"Sutton, Bushey Road",51.3684787,-0.2003649
+154,"Sutton, Bushey Road",51.3684787,-0.2003649
+154,"St Helier, Rose Hill",51.393722,-0.1876929
+154,St Helier Station,51.3899,-0.19875
+154,Morden,51.394943,-0.19446
+155,"Tooting, St George's Hospital",51.42656299999999,-0.1752284
+155,Tooting Broadway,51.427867,-0.1678142
+155,Balham,51.4439889,-0.1494105
+155,Clapham Common,51.4589252,-0.1493071
+155,Stockwell,51.46557110000001,-0.1159728
+155,Kennington Church,51.50789830000001,-0.1952076
+155,Elephant & Castle,51.4938058,-0.0977932
+156,Wimbledon,51.41833889999999,-0.2206288
+156,"Haydons Road, Plough Lane",51.42148840000001,-0.18782
+156,Wandsworth,51.45837299999999,-0.1891356
+156,Clapham Junction,51.4651737,-0.1708113
+156,Nine Elms,51.4801974,-0.1396819
+156,Vauxhall,51.4309209,-0.0936496
+157,Crystal Palace,51.4558287,-0.0714344
+157,Anerley Station,51.4123847,-0.064941
+157,Norwood Junction,51.39731,-0.07501000000000001
+157,West Croydon,51.368451,-0.09966350000000002
+157,"Stafford Road, The Chase",51.3637156,-0.1194076
+157,Wallington,51.363978,-0.151845
+157,Wallington,51.363978,-0.151845
+157,Wrythe Green,51.3768184,-0.1780163
+157,"St Helier, Rose Hill",51.3936715,-0.1871751
+157,Morden,51.40799459999999,-0.192246
+158,Chingford Mount,51.612978,-0.0177167
+158,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+158,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+158,St James's Street,51.5051953,-0.138084
+158,Markhouse Corner,51.57516529999999,-0.0298297
+158,"Leyton, Grange Park Road",51.5672498,-0.0167708
+158,"Leyton, Downsell Road",51.55411369999999,0.0003557
+158,Stratford,51.5426313,-0.0010369
+159,Streatham Station,51.4259857,-0.131308
+159,Streatham Hill Station,51.4382009,-0.1270706
+159,Brixton,51.4533088,-0.1205905
+159,Brixton,51.4533088,-0.1205905
+159,Kennington Church,51.5079351,-0.1952207
+159,Lambeth North,51.4935082,-0.1178424
+159,Lambeth North,51.4935082,-0.1178424
+159,"Whitehall, Horse Guards",51.5049111,-0.1273704
+159,Piccadilly Circus,51.5077144,-0.1406648
+159,Oxford Circus,51.5156424,-0.137491
+159,Oxford Circus,51.5156424,-0.137491
+159,Marble Arch,51.5133224,-0.1589956
+160,Catford Bridge,51.4448458,-0.0247399
+160,Hither Green,51.4522987,-0.0073954
+160,"Eltham, Yorkshire Grey",51.4530696,0.0357541
+160,"Eltham, High Street",51.4507673,0.0560971
+160,New Eltham Station,51.43806,0.07056
+160,Chislehurst,51.412626,0.077487
+160,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+160,Queen Mary's Hospital,51.4556562,-0.2426609
+160,Sidcup Station,51.4339345,0.1038351
+161,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+161,Mottingham,51.4335607,0.0484827
+161,Eltham Station,51.45564,0.0525
+161,Queen Elizabeth Hospital,51.4778139,0.0505587
+161,Woolwich,51.4813345,0.1309026
+161,Charlton Station,51.4867404,0.0310491
+161,North Greenwich,51.4859576,0.007494900000000001
+162,Beckenham Junction,51.4109588,-0.0258909
+162,Park Langley,51.385466,-0.0087119
+162,Bromley South,51.406025,0.013156
+162,Chislehurst,51.3867511,0.0879358
+162,"New Eltham, Fiveways",51.4350775,0.0646125
+162,"Avery Hill Road,Halfway Street",51.4422936,0.0806182
+162,Eltham Station,51.4506338,0.0570862
+163,Morden,51.4075989,-0.1922691
+163,Lower Morden,51.390593,-0.2194281
+163,Lower Morden,51.390593,-0.2194281
+163,Raynes Park,51.4084257,-0.2298751
+163,Wimbledon,51.41833889999999,-0.2206288
+163,Wimbledon,51.41833889999999,-0.2206288
+164,Sutton Station,51.3596681,-0.1911606
+164,Sutton Green,51.5480724,0.2172356
+164,"St Helier, Rose Hill",51.3940683,-0.1875979
+164,Morden,51.4075989,-0.1922691
+164,Morden,51.4075989,-0.1922691
+164,"Bushey Road, Botsford Road",51.40868529999999,-0.2155818
+164,Wimbledon,51.41833889999999,-0.2206288
+164,Wimbledon,51.41833889999999,-0.2206288
+165,"Romford, The Brewery",51.5757212,0.1798406
+165,Romford Station,51.57472449999999,0.1826519
+165,Hornchurch Town Centre,51.562254,0.218605
+165,Elm Park,51.5520615,0.2016224
+165,Rainham Tesco,51.5200061,0.1907802
+165,Rainham War Memorial,51.5185366,0.1902033
+165,"Rainham, Abbey Wood Lane",51.5292975,0.2137483
+166,Epsom Hospital,51.3251497,-0.2732057
+166,Banstead,51.3221909,-0.205046
+166,Chipstead Valley,51.3194573,-0.145129
+166,Coulsdon,51.319941,-0.141267
+166,Purley,51.339228,-0.119711
+166,"South Croydon, Bus Garage",51.3544903,-0.0968822
+166,Croydon Town Centre,51.3769529,-0.0956895
+166,West Croydon,51.368451,-0.09966350000000002
+167,Ilford,51.556619,0.076251
+167,Ilford Broadway,51.556619,0.076251
+167,"Barkingside, Fullwell Cross",51.59451199999999,0.08571999999999999
+167,Gants Hill,51.5767812,0.0661732
+167,Buckhurst Hill,51.627572,0.034513
+167,Loughton,51.655942,0.068161
+168,Hampstead Heath,51.5608294,-0.1629416
+168,Chalk Farm,51.5422732,-0.1466907
+168,Camden Town,51.5390261,-0.1425516
+168,Euston,51.5275774,-0.130909
+168,Russell Square,51.5220582,-0.1276485
+168,Holborn,51.517893,-0.1085556
+168,Aldwych,51.5116716,-0.1189217
+168,Waterloo,51.5017711,-0.109428
+168,Waterloo,51.5017711,-0.109428
+168,Bricklayer's Arms,51.4661409,-0.2174147
+168,"Old Kent Road, Tesco",51.4854662,-0.0700918
+169,Clayhall,51.5918921,0.05992909999999999
+169,Barkingside,51.5899246,0.08387420000000001
+169,Newbury Park,51.5734779,0.08897669999999999
+169,Ilford,51.5531267,0.07355149999999999
+169,Ilford Broadway,51.556619,0.076251
+169,Barking,51.5287766,0.03377
+170,"Roehampton, Danebury Avenue",51.4498696,-0.2433181
+170,Putney Heath,51.4524424,-0.2298485
+170,Wandsworth,51.47715849999999,-0.1301676
+170,Wandsworth,51.47715849999999,-0.1301676
+170,"Wandsworth, East Hill",51.4573489,-0.1880728
+170,Clapham Junction,51.4651737,-0.1708113
+170,"Battersea Bridge, South Side",51.4811674,-0.1725411
+170,"Battersea Bridge, North Side",51.4811674,-0.1725411
+170,Victoria,51.5099822,-0.117819
+171,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+171,Catford Town Centre,51.4453954,-0.0160913
+171,Brockley Rise,51.4497569,-0.039271
+171,New Cross Gate,51.4749942,-0.0465004
+171,Peckham,51.46075519999999,-0.06064029999999999
+171,Camberwell Green,51.4748827,-0.0921158
+171,Elephant & Castle,51.49402689999999,-0.1005177
+171,Waterloo,51.5007581,-0.1077651
+171,Aldwych,51.5116193,-0.1188998
+171,Holborn,51.51789309999999,-0.1085567
+172,Brockley Rise,51.45158259999999,-0.0387554
+172,Brockley Cross,51.465303,-0.0363334
+172,New Cross Gate,51.4749904,-0.0403466
+172,"Old Kent Road, Tesco",51.4854662,-0.0700918
+172,Bricklayer's Arms,51.4661409,-0.2174147
+172,New Kent Road,51.4938888,-0.0906269
+172,Elephant & Castle,51.4938058,-0.0977932
+172,Elephant & Castle,51.4938058,-0.0977932
+172,Waterloo,51.5016858,-0.1093259
+172,Waterloo,51.5016858,-0.1093259
+172,Aldwych,51.5116716,-0.1189217
+172,Ludgate Circus,51.51413830000001,-0.1043402
+172,Ludgate Circus,51.51413830000001,-0.1043402
+172,St. Paul's,51.4309209,-0.0936496
+173,Beckton Station,51.5144016,0.06153319999999999
+173,Ripple Road,51.53527949999999,0.0898127
+173,Ripple Road,51.53527949999999,0.0898127
+173,"Dagenham, Kent Avenue",51.5235188,0.1516733
+173,Becontree Heath,51.5609465,0.1488995
+173,Chadwell Heath,51.5722283,0.141995
+173,Little Heath,51.4854017,0.0495252
+173,King George Hospital,51.5789575,0.1124443
+174,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
+174,"Harold Hill, Gooshays Drive",51.60684579999999,0.2239714
+174,Gallows Corner,51.59188200000001,0.214546
+174,"Gallows Corner, Main Road",51.5922565,0.2142701
+174,Romford Market,51.5790739,0.1813886
+174,Romford Station,51.57472449999999,0.1826519
+174,"Dagenham Road, Eastbrook School",51.55144010000001,0.1635667
+174,Dagenham Hthway,51.53813710000001,0.1485571
+174,"Dagenham, New Road",51.5231641,0.1783295
+174,"Dagenham, Marsh Way",51.5170612,0.1696416
+175,Hillrise Estate,51.60715159999999,0.1723829
+175,Collier Row,51.5977138,0.1535519
+175,"Romford, Parkside Avenue",51.5903277,0.1801191
+175,Romford North Street Bus Garage,51.5823836,0.1761951
+175,Romford Station,51.57472449999999,0.1826519
+175,"Romford, Queen's Hospital",51.5688117,0.1807796
+175,Becontree Heath,51.5609465,0.1488995
+175,Dagenham Heathway,51.5378261,0.1479616
+175,"Dagenham, New Road",51.5281707,0.1574915
+176,Penge,51.41388490000001,-0.0570112
+176,Sydenham,51.3817082,-0.09405849999999999
+176,Forest Hill,51.4488504,-0.0544969
+176,Dulwich Library,51.4488677,-0.07447669999999999
+176,East Dulwich,51.455147,-0.084622
+176,Camberwell Green,51.4741358,-0.09309769999999999
+176,Camberwell Green,51.4741358,-0.09309769999999999
+176,Elephant & Castle,51.4940316,-0.1005179
+176,Waterloo,51.50135650000001,-0.1091323
+176,Aldwych,51.5116716,-0.1189217
+176,Trafalgar Square,51.4881451,-0.0887212
+176,Tottenham Court Road,51.5223956,-0.1356586
+177,Thamesmead,51.50575809999999,0.1100586
+177,"Thamesmead, Boiler House",51.50575809999999,0.1100586
+177,Plumstead Station,51.4896774,0.0847463
+177,"Plumstead, Lakedale Road",51.4827083,0.0910057
+177,Woolwich,51.48116,0.1300398
+177,Woolwich,51.48116,0.1300398
+177,Charlton,51.63522039999999,-0.0392038
+177,East Greenwich,51.4309209,-0.0936496
+177,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+177,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+177,Greenwich Station,51.4780469,-0.013361
+177,Deptford Bridge,51.4744304,-0.0224546
+177,New Cross,51.4748585,-0.0462917
+177,New Cross Gate,51.4748585,-0.0462917
+177,Peckham,51.4603742,-0.06051840000000001
+178,Woolwich,51.4622079,0.1474666
+178,Queen Elizabeth Hospital,51.4778139,0.0505587
+178,"Shooters Hill Road, Sun-in-the-Sands",51.4751637,0.025465
+178,Kidbrooke,51.46108479999999,0.0261346
+178,Lee Green,51.3916532,0.1019578
+178,Lewisham Station,51.4652098,-0.0131213
+179,Chingford Station,51.6331421,0.0098588
+179,Woodford Wells,51.6148389,0.0281739
+179,Woodford Green,51.59981939999999,0.0199759
+179,South Woodford,51.5912671,0.0264721
+179,Gants Hill,51.5791987,0.0640264
+179,Ilford Station,51.5587899,0.0691212
+179,Ilford,51.5528331,0.07363979999999999
+180,"Belvedere, Industrial Area",51.48516499999999,0.14827
+180,Abbey Wood,51.48967099999999,0.119721
+180,Thamesmead East,51.50575809999999,0.1100586
+180,Plumstead Bus Garage,51.4913502,0.084419
+180,Woolwich,51.462271,0.1474771
+180,Woolwich,51.462271,0.1474771
+180,Charlton,51.48365769999999,0.0398658
+180,East Greenwich,51.4309209,-0.0936496
+180,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+180,Lewisham Station,51.4652098,-0.0131213
+180,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+181,Lewisham Station,51.4652098,-0.0131213
+181,Ladywell,51.4566649,-0.0154446
+181,Hither Green,51.45276029999999,-0.0071555
+181,Catford,51.4453954,-0.0160913
+181,Catford,51.4453954,-0.0160913
+181,"Catford, St Dunstan's",51.4430327,-0.0237655
+181,Lower Sydenham,51.42603219999999,-0.0325314
+181,Lower Sydenham,51.42603219999999,-0.0325314
+181,"Downham, Bromley Road",51.4346845,-0.0176083
+181,Grove Park,51.5921921,-0.2590079
+182,"Harrow Weald, Oxhey Lane",51.6155169,-0.3609869
+182,Harrow Weald,51.6052581,-0.3380395
+182,Harrow & Wealdstone Station,51.59172359999999,-0.3343587
+182,Harrow,51.552225,-0.3025793
+182,Sudbury,51.561682,-0.3318179
+182,Wembley Arena,51.558096,-0.282586
+182,Wembley Stadium Station,51.55418960000001,-0.286004
+182,Brent Town Hall,51.5665579,-0.2736435
+182,"Neasden, Shopping Centre",51.5626819,-0.2536987
+182,Staples Corner,51.5714404,-0.2319415
+182,Brent Cross,51.5763589,-0.2236956
+183,Golders Green,51.57602559999999,-0.2052126
+183,"Hendon, Queens Road",51.5824283,-0.226999
+183,West Hendon Broadway,51.5777099,-0.2399904
+183,Kingsbury Circle,51.5850061,-0.2814251
+183,"Kingsbury, The Mall",51.5853499,-0.2782546
+183,Northwick Park Station,51.4309209,-0.0936496
+183,Harrow,51.552225,-0.3025793
+183,North Harrow,51.58412800000001,-0.3644343
+183,Pinner,51.6039322,-0.4148169
+184,Turnpike Lane Station,51.5904278,-0.1027587
+184,Wood Green,51.5971722,-0.1098021
+184,Alexandra Park School,51.602153,-0.1365257
+184,Alexandra Park School,51.602153,-0.1365257
+184,Arnos Grove,51.6203322,-0.1295261
+184,Hampden Square,51.6323276,-0.1417747
+184,New Barnet,51.649276,-0.176187
+184,Barnet Church,51.6526856,-0.1992227
+184,"Barnet, Chesterfield Road",51.64658110000001,-0.2149842
+185,Lewisham Station,51.4652098,-0.0131213
+185,"Catford, Town Centre",51.4453954,-0.0160913
+185,Forest Hill,51.4487815,-0.0539697
+185,Dulwich Library,51.4488677,-0.07447669999999999
+185,East Dulwich,51.45482630000001,-0.0851263
+185,East Dulwich,51.45482630000001,-0.0851263
+185,Camberwell Green,51.4748827,-0.0921158
+185,Camberwell Green,51.4748827,-0.0921158
+185,Vauxhall,51.4861671,-0.12172
+185,Victoria,51.4309209,-0.0936496
+186,Northwick Park Hospital,51.5753935,-0.3201711
+186,Harrow,51.580559,-0.341995
+186,Harrow & Wealdstone Station,51.59172359999999,-0.3343587
+186,Belmont Circle,51.6010493,-0.3180225
+186,Belmont Circle,51.6010493,-0.3180225
+186,Edgware,51.61548819999999,-0.2609598
+186,Edgware,51.61548819999999,-0.2609598
+186,Apex Corner,51.4369075,-0.3784005
+186,Mill Hill Broadway,51.6133816,-0.2463566
+186,Hendon Central,51.583202,-0.226399
+186,Brent Cross,51.5763589,-0.2236956
+187,Central Middlesex Hospital,51.530944,-0.2690778
+187,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+187,Kensal Rise,51.5345071,-0.2250186
+187,Queens Park,51.5345448,-0.2043853
+187,Warwick Avenue,51.5248259,-0.1882752
+187,Swiss Cottage,51.5425872,-0.1724737
+187,"Finchley Road, O2 Centre",51.5478286,-0.1814281
+188,North Greenwich,51.4859576,0.007494900000000001
+188,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+188,Deptford Church Street,51.4778325,-0.0227861
+188,Surrey Quays,51.4944172,-0.0383063
+188,Canada Water,51.4962989,-0.0482742
+188,Elephant & Castle,51.4938058,-0.0977932
+188,Elephant & Castle,51.4938058,-0.0977932
+188,Bricklayer's Arms,51.4661409,-0.2174147
+188,New Kent Road,51.4938526,-0.0906279
+188,Waterloo,51.5010694,-0.1088086
+188,Aldwych,51.5116716,-0.1189217
+188,Russell Square,51.52205739999999,-0.1276504
+189,Brent Cross,51.5763589,-0.2236956
+189,"Cricklewood, Pennine Drive",51.5644748,-0.215895
+189,Cricklewood Broadway,51.5569668,-0.2159914
+189,Kilburn High Road Station,51.537243,-0.192318
+189,Baker Street Station,51.5231548,-0.156863
+189,Baker Street Station,51.5231548,-0.156863
+189,Portman Square,51.5161534,-0.1560125
+189,Marble Arch,51.5133224,-0.1589956
+190,Richmond,51.56304249999999,-0.002005100000000001
+190,North Sheen,51.4644443,-0.2733717
+190,"Chiswick, Edensor Road",51.4821173,-0.255696
+190,Hammersmith,51.4932648,-0.2207996
+190,Hammersmith,51.4932648,-0.2207996
+190,West Brompton,51.483494,-0.196802
+191,Edmonton Green,51.6248126,-0.0581806
+191,"Ponders End, Nag's Head Road",51.6452225,-0.04863729999999999
+191,Enfield,51.6522994,-0.0807119
+191,"Southbury, Dearsley Road",51.64991610000001,-0.06317049999999999
+191,Enfield,51.6522994,-0.0807119
+191,Carterhatch,51.6607085,-0.06135640000000001
+191,Enfield Highway,51.652918,-0.041145
+191,Brimsdown,51.6628622,-0.0308497
+192,Enfield,51.6522994,-0.0807119
+192,Enfield Town Station,51.6520903,-0.07934469999999999
+192,Great Cambridge Road,51.6466396,-0.06045279999999999
+192,Great Cambridge Road,51.6466396,-0.06045279999999999
+192,Bush Hill Park,51.6445559,-0.06559659999999999
+192,Edmonton Green,51.6248126,-0.0581806
+192,"Angel Road, Superstores",51.6130441,-0.0522623
+192,Tottenham Hale,51.5892808,-0.06105049999999999
+193,"Romford, Queens Hospital",51.5688117,0.1807796
+193,Romford Market,51.5790739,0.1813886
+193,Romford Station,51.57472449999999,0.1826519
+193,"Hornchurch, Town Centre",51.562254,0.218605
+193,Hornchurch Station,51.55406929999999,0.2190275
+193,"Hornchurch, Bevan Way",51.5504909,0.2293935
+193,County Park Estate,51.4309209,-0.0936496
+194,Lower Sydenham,51.42603219999999,-0.0325314
+194,Lower Sydenham,51.42603219999999,-0.0325314
+194,Penge,51.41388490000001,-0.0570112
+194,"Beckenham, War Memorial",51.406914,-0.0320175
+194,Elmers End Green,51.3987339,-0.0436577
+194,Eden Park,51.3959047,-0.0312291
+194,Shirley,51.4309209,-0.0936496
+194,Shirley Inn,51.3744006,-0.05023610000000001
+194,Shirley Park,51.4309209,-0.0936496
+194,East Croydon,51.3750493,-0.0926978
+194,West Croydon,51.368451,-0.09966350000000002
+195,Charville Lane Estate,51.53883769999999,-0.4249346
+195,"Hayes North, Brook House",51.5323301,-0.4196085
+195,"Uxbridge Road, Lansbury Drive",51.5157566,-0.3980216
+195,Hayes & Harlington Station,51.5029848,-0.4203779
+195,Bull's Bridge,51.4999134,-0.4066811
+195,"Southall, Town Hall",51.5113272,-0.3751471
+195,Ealing Hospital,51.5075205,-0.3465216
+195,Hanwell Broadway,51.5066369,-0.3383229
+195,Great West Road,51.4761743,-0.3832373
+195,"Brentford, County Court",51.4842409,-0.3043609
+196,Elephant & Castle,51.4940507,-0.1005186
+196,Kennington Lane,51.48738669999999,-0.1126558
+196,Vauxhall,51.4861671,-0.12172
+196,Stockwell,51.466345,-0.1167604
+196,Brixton,51.4722042,-0.1127279
+196,Herne Hill,51.46079049999999,-0.09614919999999999
+196,Herne Hill,51.46079049999999,-0.09614919999999999
+196,Tulse Hill Station,51.43986,-0.10505
+196,Upper Norwood,51.41376716037048, -0.09204081941649297
+196,Norwood Junction,51.39731,-0.07501000000000001
+197,Peckham,51.4599566,-0.05951149999999999
+197,Peckham Rye,51.4599566,-0.05951149999999999
+197,Dulwich Library,51.4488677,-0.07447669999999999
+197,Forest Hill,51.4487815,-0.0539697
+197,Penge,51.41330120000001,-0.0509863
+197,Norwood Junction,51.39731,-0.07501000000000001
+197,Lower Addiscombe Road,51.3796147,-0.0747988
+197,East Croydon,51.3769529,-0.0956895
+197,Croydon Town Centre,51.3769529,-0.0956895
+198,Shrublands,51.3660734,-0.0295354
+198,Shirley,51.4309209,-0.0936496
+198,Shirley Inn,51.3744006,-0.05023610000000001
+198,"Addiscombe Road, Shirley Road",51.3750364,-0.0761587
+198,West Croydon,51.368451,-0.09966350000000002
+198,Thornton Heath Pond,51.3941232,-0.1146955
+198,Thornton Heath Station,51.3985835,-0.1000937
+198,"Thornton Heath, High Street",51.396747,-0.105523
+199,Canada Water,51.4962989,-0.0482742
+199,Surrey Quays,51.4972243,-0.0505153
+199,Pepys Estate,51.4309209,-0.0936496
+199,"Deptford, Church Street",51.4807988,-0.0231099
+199,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+199,Lewisham Centre,51.4606377,-0.0109996
+199,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+199,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+200,Raynes Park,51.4084257,-0.2298751
+200,Copse Hill,51.414603,-0.2468798
+200,Wimbledon,51.41833889999999,-0.2206288
+200,Wimbledon,51.41833889999999,-0.2206288
+200,Colliers Wood,51.41704439999999,-0.1778555
+200,Phipp's Bridge,51.4954779,-0.1463109
+200,Mitcham,51.42185670000001,-0.1448831
+201,Morden,51.40636560000001,-0.1919791
+201,Mitcham,51.4210631,-0.1450061
+201,Mitcham,51.4210631,-0.1450061
+201,"Streatham, St Leonard's Church",51.42926610000001,-0.1311095
+201,Streatham Hill Station,51.4382009,-0.1270706
+201,Tulse Hill Station,51.43986,-0.10505
+201,Herne Hill,51.4531448,-0.1008164
+202,Crystal Palace,51.4547456,-0.07225070000000001
+202,Sydenham,51.3826752,-0.0933617
+202,Lower Sydenham,51.42603219999999,-0.0325314
+202,"Catford, St. Dunstan's",51.4430327,-0.0237655
+202,"Catford, Town Centre",51.4453954,-0.0160913
+202,"Catford, Town Centre",51.4453954,-0.0160913
+202,Lee Green,51.3916532,0.1019578
+202,Blackheath Village,51.4657729,0.0091238
+202,"Blackheath, Royal Standard",51.4779946,0.0202001
+203,"Hounslow, Bus Station",51.4708688,-0.3546457
+203,"Hounslow, Bell Corner",51.468569,-0.3666325
+203,Hounslow West,51.469435,-0.3837709
+203,Hatton Cross,51.4651031,-0.4157165
+203,Hatton Cross,51.4651031,-0.4157165
+203,Bedfont Green,51.450743,-0.4215865
+203,Ashford Hospital,51.4309209,-0.0936496
+203,"Staines, Crooked Billet Roundabout",51.43148,-0.515525
+203,Staines,51.4567807,-0.4135941
+204,Sudbury,51.5556591,-0.3171114
+204,Wembley High Road,51.5534192,-0.2873889
+204,"Preston Road, East Lane",51.5632313,-0.3134248000000001
+204,Kingsbury Circle,51.5853429,-0.2812115
+204,Kingsbury Circle,51.5853429,-0.2812115
+204,Colindale,51.5896908,-0.2491029
+204,Grahame Park,51.6017283,-0.2444205
+204,Burnt Oak,51.602809,-0.266965
+204,Edgware,51.61548819999999,-0.2609598
+205,Paddington,51.515973,-0.174943
+205,Marylebone,51.5188746,-0.1498955
+205,Baker Street Station,51.5231548,-0.156863
+205,Warren Street,51.5240516,-0.1399547
+205,Warren Street,51.5240516,-0.1399547
+205,Euston,51.5256866,-0.1350478
+205,King's Cross,51.53073190000001,-0.1194466
+205,Islington Angel,51.5346761,-0.1042905
+205,Old Street Station,51.5256719,-0.0874922
+205,Aldgate,51.5134365,-0.0772463
+205,Aldgate,51.5134365,-0.0772463
+205,Whitechapel,51.518398,-0.0628557
+205,Mile End,51.52214499999999,-0.045741
+205,Bow Church,51.5287753,-0.0167013
+206,"Wembley Park, The Paddocks",51.5677761,-0.2721636
+206,"Brent Park, Superstores",51.55263000000001,-0.2568869
+206,Craven Park,51.5771634,-0.063669
+206,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+206,Queen's Park,51.5345448,-0.2043853
+206,Kilburn Park,51.5285878,-0.1958083
+207,Hayes By-Pass,51.51593,-0.398889
+207,Ealing Hospital,51.5075205,-0.3465216
+207,Ealing Broadway,51.514042,-0.3015746
+207,Southall Town Hall,51.5113272,-0.3751471
+207,"Acton, High Street",51.507503,-0.2729245
+207,Acton Vale,51.50837199999999,-0.27444
+207,Shepherd's Bush Market Station,51.5056503,-0.2262516
+207,White City,51.51146199999999,-0.2376332
+208,Lewisham Station,51.4652098,-0.0131213
+208,Ladywell,51.4566319,-0.0153652
+208,"Catford, Town Centre",51.4453954,-0.0160913
+208,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+208,"Downham, Bromley Road",51.4336021,-0.0185754
+208,"Bromley, Market Square",51.4056858,0.0148563
+208,Bromley South,51.406025,0.013156
+208,Bromley South,51.406025,0.013156
+208,"Bromley Common, Crown Lane",51.3836929,0.03937239999999999
+208,Petts Wood,51.389636,0.08195
+208,"Orpington, War Memorial",51.373203,0.09753479999999999
+208,"Orpington, Perry Hall Road",51.38329659999999,0.0938267
+209,Mortlake,51.48258389999999,-0.286561
+209,Mortlake,51.48258389999999,-0.286561
+209,Barnes Pond,51.4731208,-0.2468688
+209,Hammersmith,51.5011022,-0.22881
+210,Finsbury Park Station,51.5646425,-0.1058553
+210,Hornsey Rise,51.5721143,-0.12519
+210,Archway,51.5738502,-0.1412403
+210,Highgate Village,51.5681273,-0.1396432
+210,Golders Green,51.5740013,-0.1987725
+210,Brent Cross,51.5763589,-0.2236956
+211,Hammersmith,51.491187,-0.223731
+211,Fulham Broadway,51.4800648,-0.1957697
+211,"Chelsea, Redcliffe Gardens",51.4890213,-0.1892602
+211,Sloane Square,51.4927684,-0.1570174
+211,"Victoria, Coach Station",51.4924744,-0.1482485
+211,Parliament Square,51.5010421,-0.1268514
+211,Waterloo,51.500072,-0.1074168
+212,Chingford Station,51.6331421,0.0098588
+212,Chingford Hatch,51.61703,-0.000263
+212,Highams Park,51.6083754,0.0014712
+212,"Walthamstow, Beacontree Avenue",51.595736,0.0045318
+212,Walthamstow Central,51.5830128,-0.019886
+212,St James Street,51.5064993,-0.1393328
+213,Kingston,51.4116616,-0.2080648
+213,Kingston,51.4116616,-0.2080648
+213,"New Malden, Coombe Road",51.4094312,-0.2586718
+213,"New Malden, Fountain Roundabout",51.3978781,-0.2554973
+213,Worcester Park,51.38029,-0.24468
+213,North Cheam,51.3619271,-0.2189255
+213,Cheam,51.3619271,-0.2189255
+213,"Sutton, Bushey Road",51.3684466,-0.2004401
+214,Highgate Village,51.5717035,-0.1501241
+214,Parliament Hill Fields,51.5594043,-0.151707
+214,Kentish Town,51.5482656,-0.1410885
+214,Camden Town,51.5390261,-0.1425516
+214,Camden Town,51.5390261,-0.1425516
+214,King's Cross,51.53088229999999,-0.1194892
+214,King's Cross,51.53088229999999,-0.1194892
+214,Islington Angel,51.5346761,-0.1042905
+214,Old Street Station,51.5256719,-0.0874922
+214,"Moorgate, Finsbury Square",51.5184165,-0.0889151
+215,Lee Valley Camp Site,51.65514599999999,-0.007160000000000001
+215,Yardley Lane,51.6418904,-0.0087819
+215,Chingford Mount,51.61505940000001,-0.0177717
+215,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+215,Walthamstow Central,51.5830128,-0.019886
+216,Staines,51.4657839,-0.3748097
+216,"Staines, Crooked Billet Roundabout",51.43148,-0.515525
+216,Ashford Hospital,51.4309209,-0.0936496
+216,"Sunbury, Tesco",51.414472,-0.4167217
+216,Sunbury Cross,51.4309209,-0.0936496
+216,Sunbury Village,51.4309209,-0.0936496
+216,Hampton Station,51.4158208,-0.3719119
+216,Hampton Station,51.4158208,-0.3719119
+216,Hampton Court,51.5454747,-0.1036343
+216,Hampton Wick,51.4086385,-0.3365021
+216,Kingston,51.4116616,-0.2080648
+217,Waltham Cross,51.68584389999999,-0.0330964
+217,St Ignatius College,51.6739451,-0.0549748
+217,Carterhatch,51.6590165,-0.035367
+217,Enfield Retail Park,51.6541066,-0.0578729
+217,"Southbury, Dearsley Road",51.64991610000001,-0.06317049999999999
+217,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+217,Lordship Lane,51.454366,-0.0770907
+217,Turnpike Lane Station,51.5904278,-0.1027587
+219,Wimbledon,51.41833889999999,-0.2206288
+219,Wimbledon,51.41833889999999,-0.2206288
+219,"Merton, Bus Garage",51.4165431,-0.1813083
+219,Colliers Wood,51.41704439999999,-0.1778555
+219,Tooting Broadway,51.427867,-0.1678142
+219,Tooting Bec,51.4324334,-0.1522016
+219,Tooting Bec,51.4324334,-0.1522016
+219,Wandsworth Common,51.4581475,-0.1792287
+219,Clapham Junction,51.4651737,-0.1708113
+220,Willesden Junction,51.53211630000001,-0.2433689
+220,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+220,"College Park, Scrubs Lane",51.5206904,-0.2288875
+220,North Pole Road,51.5195492,-0.2265871
+220,Shepherd's Bush,51.5051913,-0.22469
+220,Shepherd's Bush,51.5051913,-0.22469
+220,Hammersmith,51.50056009999999,-0.2280682
+220,Brook Green,51.4963863,-0.2217637
+220,Hammersmith,51.50056009999999,-0.2280682
+220,Putney Bridge,51.4644547,-0.2131459
+220,Wandsworth,51.4754967,-0.1316509
+220,Wandsworth,51.4754967,-0.1316509
+221,Edgware,51.5193526,-0.1693003
+221,Mill Hill Broadway,51.6133816,-0.2463566
+221,Mill Hill East,51.60823,-0.20996
+221,Holders Hill Circus,51.6051942,-0.2078155
+221,North Finchley,51.6135087,-0.1754198
+221,Friern Barnet,51.6255032,-0.1699775
+221,New Southgate,51.61100099999999,-0.135469
+221,Wood Green,51.5971722,-0.1098021
+221,Wood Green,51.5971722,-0.1098021
+221,Wood Green,51.5971722,-0.1098021
+221,Turnpike Lane Station,51.5904278,-0.1027587
+222,Uxbridge,51.5485,-0.479611
+222,Cowley,51.525848,-0.4820508999999999
+222,West Drayton,51.502985,-0.4654099999999999
+222,"Bath Road, Sipson Road",51.49763,-0.4623274
+222,Harlington Corner,51.4809415,-0.434335
+222,Cranford,51.4720623,-0.4055896
+222,Hounslow West,51.469435,-0.3837709
+222,"Hounslow, Bell Corner",51.468569,-0.3666325
+222,"Hounslow, Bus Station",51.4708688,-0.3546457
+223,Harrow,51.580559,-0.341995
+223,Northwick Park Hospital,51.5753935,-0.3201711
+223,Preston Road Station,51.57197,-0.29508
+223,Wembley Park,51.5585935,-0.2796126
+223,Wembley Central,51.55214429999999,-0.2965274
+224,Wembley Stadium,51.55602469999999,-0.2796177
+224,Alperton,51.539601,-0.2988365
+224,"Alperton, Sainsbury's",51.5383862,-0.3028583
+224,"Park Royal, Asda",51.52781,-0.26989
+224,Central Middlesex Hospital,51.530944,-0.2690778
+224,Craven Park,51.57750739999999,-0.0630854
+224,St. Raphael's,51.55207859999999,-0.2622574
+225,Hither Green,51.45059,-0.005551899999999999
+225,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+225,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+225,New Cross,51.4768299,-0.0499381
+225,Surrey Quays,51.4944172,-0.0383063
+225,Canada Water,51.4962989,-0.0482742
+226,Ealing Broadway,51.514042,-0.3015746
+226,Hanger Lane,51.531478,-0.2932577000000001
+226,"Park Royal, First Central",51.5326143,-0.2854417
+226,"Park Royal, Asda",51.52781,-0.26989
+226,Central Middlesex Hospital,51.530944,-0.2690778
+226,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+226,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+226,Cricklewood Broadway,51.5587708,-0.2174545
+226,"Cricklewood, Pennine Drive",51.564752,-0.2161581
+226,Golders Green,51.5740013,-0.1987725
+227,Bromley North,51.406025,0.013156
+227,"Beckenham, War Memorial",51.406914,-0.0320175
+227,Penge,51.41388490000001,-0.0570112
+227,Penge West,51.41388490000001,-0.0570112
+227,Crystal Palace,51.4537304,-0.0720673
+228,Central Middlesex Hospital,51.530944,-0.2690778
+228,Willesden Junction,51.53211630000001,-0.2433689
+228,East Acton,51.5127758,-0.2476803
+228,"East Acton, Savoy Circus",51.5140035,-0.247772
+228,White City,51.51146199999999,-0.2376332
+228,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+228,"Maida Hill, The Chippenham",51.5243627,-0.2017331
+229,Thamesmead,51.50575809999999,0.1100586
+229,Abbey Wood,51.4926116,0.1188182
+229,Belvedere,51.5036113,-0.1173103
+229,Erith,51.4654014,0.1514523
+229,"Bexleyheath, Bus Garage",51.46006930000001,0.1534245
+229,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+229,Bexley,51.4745106,0.1629532
+229,Sidcup Station,51.4339345,0.1038351
+229,Queen Mary's Hospital,51.4556562,-0.2426609
+230,Upper Walthamstow,51.5877489,0.0037911
+230,Whipps Cross,51.581499,0.0001219
+230,Walthamstow Central,51.5830128,-0.019886
+230,West Green,51.586254,-0.0867628
+230,Tottenham Hale Station,51.5890318,-0.05979599999999999
+230,Tottenham Town Hall,51.5872187,-0.0725467
+230,Turnpike Lane Station,51.5904278,-0.1027587
+230,"Green Lanes, West Green Road",51.58628849999999,-0.0860857
+230,Wood Green,51.5971722,-0.1098021
+230,Wood Green,51.5971722,-0.1098021
+231,Enfield Chase,51.65326,-0.09067
+231,Enfield,51.6522994,-0.0807119
+231,"Southbury, Dearsley Road",51.64991610000001,-0.06317049999999999
+231,"Edmonton, Cambridge Roundabout",51.4309209,-0.0936496
+231,Turnpike Lane Station,51.5904278,-0.1027587
+232,St Raphael's,51.55207859999999,-0.2622574
+232,"Brent Park, Superstores",51.55263000000001,-0.2568869
+232,"Neasden, Shopping Centre",51.5626819,-0.2536987
+232,Brent Cross,51.5763589,-0.2236956
+232,"North Circular, Colney Hatch",51.6034922,-0.1482548
+232,Colney Hatch Lane,51.6034922,-0.1482548
+232,Arnos Grove,51.619799,-0.1296871
+232,"Palmers Green, North Circular Road",51.61459499999999,-0.1012351
+232,Wood Green,51.5971722,-0.1098021
+232,Wood Green,51.5971722,-0.1098021
+232,Turnpike Lane Station,51.5904278,-0.1027587
+233,Eltham Station,51.4506338,0.0570862
+233,New Eltham,51.4322522,0.0658314
+233,Sidcup Station,51.4264863,0.1009392
+233,"Foots Cray, Ruxley Corner",51.4155255,0.1253275
+233,"Swanley, Asda",51.396609,0.17656
+233,Swanley,51.396531,0.177326
+234,"Barnet, The Spires",51.655492,-0.2033422
+234,Barnet Church,51.6526856,-0.1992227
+234,"Barnet, Odeon",51.64663059999999,-0.1865655
+234,Whetstone,51.6300102,-0.1747954
+234,Friern Barnet,51.6141967,-0.1540148
+234,Muswell Hill,51.5911816,-0.1443015
+234,East Finchley,51.592468,-0.1664342
+234,Highgate Wood,51.5827374,-0.1491754
+235,Sunbury Village,51.4309209,-0.0936496
+235,Sunbury Cross,51.4195309,-0.419749
+235,Lower Feltham,51.436601,-0.426105
+235,Hounslow Heath,51.4563954,-0.3849625
+235,"Hounslow, Bell Corner",51.468569,-0.3666325
+235,"Hounslow, Bus Station",51.4708688,-0.3546457
+235,Isleworth,51.467121,-0.329003
+235,Busch Corner,51.4788665,-0.3231269
+235,"Sunbury Village, Three Fishes",51.4191935,-0.4191503
+235,North Brentford Quarter,51.4835374,-0.3063676
+236,Finsbury Park Station,51.4309209,-0.0936496
+236,Highbury Barn,51.553813,-0.09808739999999999
+236,Newington Green,51.5514507,-0.0857535
+236,Ash Grove,51.4810279,-0.3902918
+236,Homerton,51.5478609,-0.0425903
+236,Hackney Wick,51.544579,-0.0256935
+237,Hounslow Heath,51.4563954,-0.3849625
+237,"Hounslow, Bell Corner",51.468569,-0.3666325
+237,"Hounslow, Bus Station",51.4708688,-0.3546457
+237,Busch Corner,51.4788665,-0.3231269
+237,"Brentford, Brent Lea",51.48131739999999,-0.3135051
+237,"Brentford, Half Acre",51.4844289,-0.3068293
+237,"Brentford, County Court",51.4842409,-0.3043609
+237,Chiswick Roundabout,51.4910362,-0.2816861
+237,Turnham Green,51.4953471,-0.2552808
+237,Goldhawk Road,51.4999246,-0.2373253
+237,Shepherd's Bush,51.5051913,-0.22469
+237,White City,51.51146199999999,-0.2376332
+238,Stratford,51.5426313,-0.0010369
+238,"Upton Park, Green Street",51.539482,0.0325224
+238,East Ham Station,51.5393698,0.0510659
+238,"East Ham, Ron Leighton Wat",51.5370273,0.0515902
+238,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+238,Barking,51.536563,0.075766
+240,Golders Green,51.5782699,-0.2076681
+240,"Hendon, Queens Road",51.5820274,-0.226689
+240,Mill Hill East,51.4309209,-0.0936496
+240,Mill Hill Broadway,51.6133816,-0.2463566
+240,Edgware,51.5190993,-0.1683807
+240,Edgware,51.5190993,-0.1683807
+241,Stratford City,51.5440354,-0.0053088
+241,Stratford,51.5426313,-0.0010369
+241,Plaistow,51.5268317,0.0308143
+241,Plaistow Abbey Arms,51.5222296,0.0225853
+241,Keir Hardie Estate,51.5678758,-0.0607466
+241,Canning Town,51.5189494,0.0132
+241,"Canning Town, Barking Road",51.5198077,0.0168462
+242,Homerton Hospital,51.5478609,-0.0425903
+242,"Clapton Park, Millfields",51.5575011,-0.0424329
+242,Hackney Central,51.5482344,-0.05738749999999999
+242,"Dalston, Downham Road",51.5396916,-0.0898268
+242,Dalston Junction,51.5459999,-0.0751485
+242,Shoreditch,51.5229106,-0.0777472
+242,Liverpool Street,51.5175001,-0.0826966
+242,St. Paul's,51.4309209,-0.0936496
+242,City Thameslink,51.5140438,-0.1033475
+242,Holborn,51.5175802,-0.1145147
+242,Tottenham Court Road,51.518301,-0.1317726
+243,Wood Green,51.5971722,-0.1098021
+243,"Lordship Lane, Downhills Way",51.5975545,-0.0922026
+243,"Tottenham, Town Hall",51.5872187,-0.0725467
+243,Stamford Hill,51.5696514,-0.0750199
+243,Stoke Newington,51.561175,-0.08349229999999999
+243,Stoke Newington,51.561175,-0.08349229999999999
+243,Dalston Junction,51.5459999,-0.0751485
+243,"Dalston, Downham Road",51.5394454,-0.0887965
+243,Shoreditch,51.5229106,-0.0777472
+243,Old Street Station,51.5256719,-0.0874922
+243,Clerkenwell Green,51.522739,-0.1060289
+243,Clerkenwell Green,51.522739,-0.1060289
+243,Holborn,51.5175802,-0.1145147
+243,Aldwych,51.5116193,-0.1188998
+243,Waterloo,51.49951129999999,-0.1064564
+244,Queen Elizabeth Hospital,51.4778139,0.0505587
+244,"Shooters Hill, Eaglesfield Road",51.468341,0.0723689
+244,Woolwich,51.4894752,0.06758829999999999
+244,Belmarsh,51.4967407,0.0927968
+244,Broadwater Estate,51.5944339,-0.0812275
+244,Thamesmead,51.50575809999999,0.1100586
+244,Abbey Wood,51.4926116,0.1188182
+245,"Alperton, Sainsbury's",51.5383862,-0.3028583
+245,Sudbury Town,51.5503085,-0.316207
+245,North Wembley,51.5625616,-0.3175595
+245,"Neasden, Shopping Centre",51.5626819,-0.2536987
+245,Cricklewood Bus Garage,51.56195959999999,-0.2224221
+245,Cricklewood Broadway,51.5584696,-0.2177538
+245,Golders Green,51.5784737,-0.2081693
+246,Bromley North,51.406025,0.013156
+246,Hayes,51.516758,-0.436786
+246,Hayes,51.516758,-0.436786
+246,Bromley Town Centre,51.406025,0.013156
+246,Biggin Hill,51.312059,0.032802
+246,Westerham,51.2945922,0.05822480000000001
+246,Chartwell,51.4309209,-0.0936496
+247,Barkingside,51.5899246,0.08387420000000001
+247,"Hainault, The Lowe",51.6099517,0.1092883
+247,Barkingside,51.5899246,0.08387420000000001
+247,Marks Gate,51.5901971,0.1424532
+247,Collier Row,51.5996927,0.1745949
+247,Collier Row,51.5996927,0.1745949
+247,"Romford, Parkside Avenue",51.5908267,0.1816681
+247,Romford North Street Bus Garage,51.5823836,0.1761951
+247,Romford Station,51.57472449999999,0.1826519
+248,Romford Market,51.5790739,0.1813886
+248,Romford Station,51.57472449999999,0.1826519
+248,Roneo Corner,51.5654177,0.1885364
+248,Hornchurch Town Centre,51.562254,0.218605
+248,Upminster,51.55591399999999,0.248894
+248,Upminster Park Estate,51.55591399999999,0.248894
+248,Cranham,51.5679469,0.2673702
+249,Clapham Common,51.4589252,-0.1493071
+249,Clapham Common,51.4589252,-0.1493071
+249,Balham,51.4439889,-0.1494105
+249,Tooting Bec,51.436753,-0.1618404
+249,"Streatham, St Leonards Church",51.42926610000001,-0.1311095
+249,"Norwood, Crown Point",41.4169806,-87.3653135
+249,Upper Norwood,51.41376716037048, -0.09204081941649297
+249,Crystal Palace,51.4197233,-0.0830638
+249,Anerley Station,51.4121559,-0.06571779999999999
+250,Brixton,51.4612794,-0.1156148
+250,"Streatham Hill, Telford Avenue",51.441526,-0.1353403
+250,Streatham Hill Station,51.4382009,-0.1270706
+250,Streatham Station,51.4259857,-0.131308
+250,"Streatham, Green Lane",51.4152538,-0.1182378
+250,"Thornton Heath, High Street",51.396747,-0.105523
+250,Thornton Heath Pond,51.3941232,-0.1146955
+250,West Croydon,51.368451,-0.09966350000000002
+250,Croydon Town Centre,51.3769529,-0.0956895
+251,Arnos Grove,51.622533,-0.1272224
+251,Totteridge & Whetstone,51.630241,-0.179144
+251,Highwood Hill,51.6268074,-0.2399921
+251,Mill Hill Broadway,51.6133816,-0.2463566
+251,Burnt Oak,51.4462445,0.1020482
+251,Edgware,51.588489,-0.2529778
+252,Collier Row,51.5968745,0.1643956
+252,Romford Market,51.5790739,0.1813886
+252,Romford Station,51.57472449999999,0.1826519
+252,Roneo Corner,51.5654177,0.1885364
+252,Roneo Corner,51.5654177,0.1885364
+252,Elm Park,51.55027399999999,0.1956364
+252,Sanders Draper School,51.5499174,0.215173
+252,"Hornchurch, Town Centre",51.562254,0.218605
+253,Hackney Central,51.5482344,-0.05738749999999999
+253,Clapton Pond,51.5561061,-0.05490830000000001
+253,Clapton Pond,51.5561061,-0.05490830000000001
+253,Stamford Hill,51.5696514,-0.0750199
+253,Manor House,51.4309209,-0.0936496
+253,Finsbury Park Station,51.5646425,-0.1058553
+253,Finsbury Park Station,51.5646425,-0.1058553
+253,"Holloway, Nags Head",51.55724250000001,-0.1204364
+253,"Camden Road, Brecknock Road",51.5501037,-0.1276357
+253,Camden Town,51.5390261,-0.1425516
+253,Mornington Crescent,51.479306,-0.4070643
+253,Euston,51.5250092,-0.1364643
+254,Aldgate,51.5134365,-0.0772463
+254,Whitechapel,51.5148198,-0.0650534
+254,Ash Grove,51.4803533,-0.3905511
+254,Ash Grove,51.4803533,-0.3905511
+254,Hackney Well Street,51.54482489999999,-0.04606610000000001
+254,Hackney Central,51.5482344,-0.05738749999999999
+254,Clapton Pond,51.5561061,-0.05490830000000001
+254,Stamford Hill,51.5743423,-0.0719958
+254,Manor House,51.4309209,-0.0936496
+254,Finsbury Park Station,51.5646425,-0.1058553
+254,"Holloway, Nags Head",51.55724250000001,-0.1204364
+255,Pollards Hill,51.4000406,-0.1332582
+255,Norbury,51.4085878,-0.1213899
+255,Streatham Station,51.4259857,-0.131308
+255,Streatham Hill Station,51.4382009,-0.1270706
+255,Balham,51.4439889,-0.1494105
+256,"Hornchurch, Miramar Way",51.5472385,0.2158209
+256,Hornchurch Town Centre,51.562254,0.218605
+256,Harold Wood,51.5910397,0.2328613
+256,Emerson Park,51.57201,0.225394
+256,"Harold Hill, Gooshays Drive",51.6081419,0.2227947
+256,Noak Hill,51.6218055,0.2263263
+256D,"Hornchurch, St George's Hospital",51.562254,0.218605
+256D,Noak Hill,51.6218055,0.2263263
+257,Stratford,51.5426313,-0.0010369
+257,Maryland,51.5477587,0.0005166999999999999
+257,"Leytonstone, Harrow Green",51.5582955,0.007356
+257,Leytonstone,51.5649624,0.0088141
+257,Whipps Cross,51.581499,0.0001219
+257,Walthamstow Central,51.5830128,-0.019886
+258,Watford Junction,51.66371280000001,-0.3964488
+258,Bushey Station,51.64583529999999,-0.3853817
+258,Bushey Heath,51.640213,-0.344442
+258,Harrow,51.580559,-0.341995
+258,South Harrow,51.5683717,-0.3553483
+259,Edmonton Green,51.6248126,-0.0581806
+259,"Snells Park, Sainsbury's",51.609054,-0.0691713
+259,"Tottenham, Town Hall",51.5872187,-0.0725467
+259,"Tottenham, Town Hall",51.5872187,-0.0725467
+259,Manor House,51.4309209,-0.0936496
+259,Finsbury Park Station,51.5646425,-0.1058553
+259,Finsbury Park Station,51.5646425,-0.1058553
+259,"Holloway, Nags Head",51.55724250000001,-0.1204364
+259,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+259,King's Cross,51.5347488,-0.1245845
+260,White City,51.51146199999999,-0.2376332
+260,Shepherd's Bush,51.5051913,-0.22469
+260,"East Acton, Savoy Circus",51.5140035,-0.247772
+260,North Acton,51.5219526,-0.2580821
+260,North Acton,51.5219526,-0.2580821
+260,"Park Royal, Asda",51.52781,-0.26989
+260,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+260,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+260,Craven Park,51.577324,-0.0632167
+260,Craven Park,51.577324,-0.0632167
+260,"Willesden, Bus Garage",51.5474482,-0.2394372
+260,Cricklewood Broadway,51.55914019999999,-0.2181392
+260,Golders Green,51.5740013,-0.1987725
+261,Lewisham Station,51.4652098,-0.0131213
+261,Lee Green,51.4493331,0.0204837
+261,Grove Park,51.4329249,0.021203
+261,Bromley North,51.40833,0.01702
+261,Bromley South,51.406025,0.013156
+261,"Bromley Common, Crown Lane",51.3836942,0.0393714
+261,"Bromley Common, Bus Garage",51.38774,0.0363217
+261,Princess Royal Hospital,51.3661498,0.05819390000000001
+262,"East Beckton, Sainsbury's",51.5212249,0.0669226
+262,Gallions Reach Shopping Park,51.5166002,0.0783827
+262,Gallions Reach Station,51.5090228,0.07172769999999999
+262,Beckton Station,51.5144016,0.06153319999999999
+262,"Plaistow, Greengate Street",51.5260178,0.0281265
+262,Plaistow,51.5268317,0.0308143
+262,Stratford,51.5426313,-0.0010369
+263,Highbury & Islington,51.5569649,-0.0979656
+263,Highbury & Islington,51.5569649,-0.0979656
+263,Holloway Nags Head,51.55724250000001,-0.1204364
+263,Archway,51.4309209,-0.0936496
+263,East Finchley,51.592468,-0.1664342
+263,East Finchley,51.592468,-0.1664342
+263,North Finchley,51.6135087,-0.1754198
+263,Whetstone,51.6300102,-0.1747954
+263,"Barnet, Odeon",51.64663059999999,-0.1865655
+263,Barnet Church,51.6526856,-0.1992227
+263,Barnet Hospital,51.6508236,-0.2137361
+264,Croydon Town Centre,51.3769529,-0.0956895
+264,West Croydon,51.368451,-0.09966350000000002
+264,"Mitcham Road, Purley Way",51.38380189999999,-0.1175218
+264,Mitcham,51.402869,-0.166709
+264,Tooting Broadway,51.427867,-0.1678142
+264,"Tooting, St George's Hospital",51.42656299999999,-0.1752284
+265,Putney Bridge,51.4631911,-0.2111601
+265,Barnes Common,51.4681254,-0.2413995
+265,Barnes Common,51.4681254,-0.2413995
+265,Roehampton,51.4484339,-0.2397592
+265,"Roehampton, Bessborough Road",51.445746,-0.2391544
+265,"Roehampton, Bessborough Road",51.445746,-0.2391544
+265,Roehampton Vale,51.4388194,-0.2491381
+265,Shannon Corner,51.3993558,-0.2429132
+265,"New Malden, Fountain Roundabout",51.3978781,-0.2554973
+265,Tolworth,51.3821133,-0.2828034
+266,Hammersmith,51.491187,-0.223731
+266,Seven Stars Corner,51.4309209,-0.0936496
+266,Acton Vale,51.5065594,-0.2567913
+266,"Acton, High Street",51.5084951,-0.2754782000000001
+266,North Acton,51.5219526,-0.2580821
+266,North Acton,51.5219526,-0.2580821
+266,Willesden Junction,51.53211630000001,-0.2433689
+266,Craven Park,51.5769799,-0.0630819
+266,Craven Park,51.5769799,-0.0630819
+266,Cricklewood Broadway,51.559223,-0.2182346
+266,Staples Corner,51.5714404,-0.2319415
+266,Brent Cross,51.5763589,-0.2236956
+267,Hammersmith,51.491187,-0.223731
+267,Ravenscourt Park,51.4947984,-0.2396908
+267,"Stamford Brook, Chiswick Lane",51.49492,-0.24568
+267,Turnham Green,51.49203019999999,-0.2663174
+267,Chiswick Roundabout,51.4910362,-0.2816861
+267,"Brentford, County Court",51.4842409,-0.3043609
+267,"London Road, Chertsey Road",51.4483827,-0.3549402
+267,Twickenham,51.4535082,-0.3301491
+267,Fulwell,51.4331018,-0.3520137
+268,Golders Green,51.5740013,-0.1987725
+268,Whitestone Pond,51.5614553,-0.1799757
+268,Swiss Cottage,51.5425872,-0.1724737
+268,"Finchley Road, O2 Centre",51.5478286,-0.1814281
+269,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+269,Bexleyheath Library,51.45587399999999,0.1439466
+269,Bexley,51.439933,0.154327
+269,"Albany Park, Foots Cray Lane",51.4372375,0.1193106
+269,Sidcup Station,51.4339345,0.1038351
+269,Queen Mary's Hospital,51.4556562,-0.2426609
+269,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+269,Bromley North,51.406025,0.013156
+270,Putney Bridge,51.4669613,-0.2129017
+270,Wandsworth,51.4741331,-0.1330686
+270,"Garratt Lane, Wimbledon Road",51.4409636,-0.1869488
+270,"Garratt Lane, Wimbledon Road",51.4409636,-0.1869488
+270,Tooting Broadway,51.427867,-0.1678142
+270,Tooting Station,51.41986989999999,-0.16136
+270,Mitcham,51.419721,-0.1471023
+270,Mitcham,51.419721,-0.1471023
+271,Highgate Village,51.5717035,-0.1501241
+271,Archway,51.4309209,-0.0936496
+271,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+271,Highbury & Islington,51.5569649,-0.0979656
+271,Old Street Station,51.5256719,-0.0874922
+271,"Moorgate, Finsbury Square",51.5184165,-0.0889151
+272,"Chiswick, Grove Park",51.481631,-0.272505
+272,Turnham Green,51.49203019999999,-0.2663174
+272,Acton Vale,51.5065594,-0.2567913
+272,East Acton,51.5127758,-0.2476803
+272,White City,51.51146199999999,-0.2376332
+272,Shepherds Bush,51.5051913,-0.22469
+273,"Lewisham, Tesco",51.4414579,-0.0117006
+273,Lewisham Shopping Centre,51.46175909999999,-0.0119106
+273,Lee Green,51.4493331,0.0204837
+273,Grove Park,51.4329249,0.021203
+273,"Dunkery Road, Mottingham Road",51.4288147,0.050542
+273,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+273,St Marys Cray,51.385993,0.113061
+273,St Marys Cray,51.385993,0.113061
+273,Petts Wood,51.389636,0.08195
+274,Islington Angel,51.5346761,-0.1042905
+274,"Caledonian Road, Copenhagen Street",51.5389986,-0.1164184
+274,Market Road,51.5455568,-0.1249446
+274,Camden Town,51.5390261,-0.1425516
+274,Camden Town,51.5390261,-0.1425516
+274,London Zoo,51.5352875,-0.1534303
+274,Lord's Cricket Ground,51.52983099999999,-0.1721564
+274,Baker Street Station,51.5231548,-0.156863
+274,Portman Square,51.5161534,-0.1560125
+274,Marble Arch,51.5132225,-0.1588937
+275,St James Street,51.5064993,-0.1393328
+275,Walthamstow Central,51.5830128,-0.019886
+275,"Walthamstow, Beacontree Avenue",51.595736,0.0045318
+275,Mill lane,51.5521985,-0.1932197
+275,Highams Park,51.6083754,0.0014712
+275,Woodford Green,51.6016983,0.019011
+275,Woodford Bridge,51.6016983,0.019011
+275,Barkingside,51.5899246,0.08387420000000001
+275,Barkingside,51.5899246,0.08387420000000001
+276,Newham Hospital,51.5222415,0.0325405
+276,"Plaistow, Greengate Street",51.527444,0.027621
+276,"Canning Town, Barking Road",51.5202859,0.0185776
+276,West Ham Station,51.5278232,0.0042832
+276,Stratford,51.5426313,-0.0010369
+276,Bow Church,51.5287753,-0.0167013
+276,Bow Church,51.5287753,-0.0167013
+276,Hackney Wick,51.544579,-0.0256935
+276,Homerton Hospital,51.5478609,-0.0425903
+276,Stoke Newington,51.561175,-0.08349229999999999
+277,Highbury Corner,51.54602329999999,-0.1022688
+277,Mildmay Park,51.5488355,-0.0843157
+277,Dalston Junction,51.5459999,-0.0751485
+277,Hackney Well Street,51.5450519,-0.046374
+277,"South Hackney, Church Crescent",51.5882451,-0.1449718
+277,Mile End,51.52354529999999,-0.0330122
+277,"Limehouse, Burdett Road",51.5165953,-0.0296452
+277,Canary Wharf,51.5054306,-0.0235333
+277,Crossharbour,51.4958465,-0.0145118
+279,Waltham Cross,51.68584389999999,-0.0330964
+279,Enfield Highway,51.652918,-0.041145
+279,"Ponders End, Bus Garage",51.6452225,-0.04863729999999999
+279,Edmonton Green,51.6248126,-0.0581806
+279,"Snells Park, Sainsburys",51.609054,-0.0691713
+279,"Tottenham, Town Hall",51.5872187,-0.0725467
+279,Seven Sisters,51.582652,-0.0747232
+279,Manor House,51.4309209,-0.0936496
+280,"Tooting, St. George's Hospital",51.42656299999999,-0.1752284
+280,Tooting Broadway,51.427867,-0.1678142
+280,Mitcham,51.402869,-0.166709
+280,Mitcham,51.402869,-0.166709
+280,"St Helier, Rose Hill",51.3881851,-0.1893768
+280,Sutton Town Centre,51.3614279,-0.193961
+280,Sutton Station,51.3614279,-0.193961
+280,Belmont,51.601249,-0.3192749
+281,Tolworth,51.3801004,-0.2861237
+281,"Tolworth, Red Lion Road",51.3788084,-0.2915515
+281,Surbiton,51.39400999999999,-0.302662
+281,"Kingston, Brook Street",51.41233,-0.300689
+281,Kingston,51.41233,-0.300689
+281,Hampton Wick,51.413541,-0.321331
+281,Teddington,51.4268694,-0.3338681
+281,Fulwell,51.4331018,-0.3520137
+281,Twickenham,51.4453043,-0.3375429
+281,"Twickenham, Rugby Stadium",51.4453043,-0.3375429
+281,Hospital Bridge Roundabout,51.44267,-0.3652385
+281,Whitton Church,51.4538478,-0.3732651
+281,"Hounslow, Bus Station",51.4708688,-0.3546457
+282,Ealing Hospital,51.5075205,-0.3465216
+282,"Iron Bridge, Uxbridge Road",51.509837,-0.3549224
+282,Greenford Broadway,51.5279556,-0.3540139
+282,"Yeading, White Hart",51.60520289999999,-0.0790162
+282,Northolt,51.546615,-0.373103
+282,"Field End Road, Victoria Road",51.5696578,-0.3900522
+282,Eastcote,51.5512622,-0.3732052
+282,Northwood Hills,51.6004243,-0.4098652
+282,Northwood Station,51.61028899999999,-0.428278
+282,Mount Vernon Hospital,51.6153975,-0.4455072
+283,East Acton,51.5127758,-0.2476803
+283,"Wood Lane, Du Cane Road",51.5151603,-0.2492864
+283,Shepherd's Bush,51.5051913,-0.22469
+283,"White City, Leisure Centre",51.51146199999999,-0.2376332
+283,Hammersmith,51.491187,-0.223731
+284,Lewisham Station,51.4652098,-0.0131213
+284,Ladywell,51.45589709999999,-0.0219523
+284,"Catford, Town Centre",51.4453954,-0.0160913
+284,Downham,51.4241172,0.009519699999999999
+284,Grove Park,51.4329249,0.021203
+284,Grove Park Cemetery,51.4246215,0.0364068
+285,Heathrow Central,51.4724711,-0.4544586
+285,"Bath Road, Sipson Road",51.4911429,-0.4575516
+285,Harlington Corner,51.4809415,-0.434335
+285,Hatton Cross,51.4651031,-0.4157165
+285,Feltham Station,51.4480215,-0.4090095
+285,"Hanworth, Apex Corner",51.4369075,-0.3784005
+285,"Hanworth, Apex Corner",51.4369075,-0.3784005
+285,"Hampton, Sainsbury's",51.4264198,-0.3776108
+285,Teddington,51.4268694,-0.3338681
+285,Hampton Wick,51.413541,-0.321331
+285,Kingston,51.41233,-0.300689
+286,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+286,East Greenwich,51.4309209,-0.0936496
+286,"Blackheath, Royal Standard",51.4779946,0.0202001
+286,Eltham Station,51.45564,0.0525
+286,"Eltham, High Street",51.450501,0.0628537
+286,Avery Hill,51.451434,0.076128
+286,Sidcup Station,51.4339345,0.1038351
+286,Queen Mary's Hospital,51.4556562,-0.2426609
+287,Barking,51.536563,0.075766
+287,"Barking, London Road",51.5372918,0.0714076
+287,"Ripple Road, Lodge Avenue",51.5416682,0.1129179
+287,"Dagenham, Asda",51.5299749,0.1425747
+287,"Dagenham, New Road",51.5275921,0.1595252
+287,Rainham Tesco,51.5200061,0.1907802
+287,Rainham Tesco,51.5200061,0.1907802
+287,Rainham War Memorial,51.5185366,0.1902033
+287,"Rainham, Abbey Wood Lane",51.5292975,0.2137483
+288,"Queensbury, Morrison's",51.5942132,-0.2853683
+288,Queensbury,51.5942132,-0.2853683
+288,Burnt Oak Broadway,51.607471,-0.2749745
+288,Edgware,51.61548819999999,-0.2609598
+288,Edgware,51.61548819999999,-0.2609598
+288,Broadfields Estate,51.6267303,-0.2729243
+289,Elmers End,51.39749,-0.0474767
+289,Long Lane,51.5501784,-0.4490557
+289,Ashburton Park,51.3855119,-0.0654191
+289,West Croydon,51.368451,-0.09966350000000002
+289,Thornton Hth Pd,51.4309209,-0.0936496
+289,Waddon Marsh,51.3769818,-0.1179077
+289,"Purley Way, Colonnades",51.3563828,-0.1135816
+289,Purley,51.339228,-0.119711
+290,Staines,51.4555302,-0.4223853
+290,"Ashford, Woodthorpe Road",51.4269867,-0.4801537999999999
+290,Ashford,51.5288186,-0.0827738
+290,Sunbury Cross,51.4309209,-0.0936496
+290,"Hampton, Sainsbury's",51.4264198,-0.3776108
+290,Twickenham,51.46206979999999,-0.3316404
+291,Queen Elizabeth Hospital,51.4778139,0.0505587
+291,Woolwich,51.4894752,0.06758829999999999
+291,Woolwich,51.4894752,0.06758829999999999
+291,Woolwich,51.4894752,0.06758829999999999
+291,Plumstead Common,51.4801905,0.08438269999999999
+291,Woodlands Estate,51.4309209,-0.0936496
+292,"Borehamwood, Rossington Avenue",51.4309209,-0.0936496
+292,Borehamwood Station,51.657728,-0.272308
+292,"Borehamwood, Tesco",51.4309209,-0.0936496
+292,Stirling Corner,51.643381,-0.2551272
+292,Edgware,51.61548819999999,-0.2609598
+292,Burnt Oak,51.602809,-0.266965
+292,Apex Corner,51.4369075,-0.3784005
+292,"Colindale, Superstores",51.5942575,-0.2607018
+293,Morden,51.394943,-0.19446
+293,Lower Morden,51.3907209,-0.2248662
+293,North Cheam,51.3619271,-0.2189255
+293,Ewell Village,51.3506319,-0.2533376
+293,Epsom,51.4309209,-0.0936496
+293,Epsom Hospital,51.3251497,-0.2732057
+294,Havering Park,51.607707,0.157121
+294,Collier Row,51.5996927,0.1745949
+294,"Romford, Parkside Avenue",51.5905318,0.1818613
+294,Romford North Street Bus Garage,51.5823836,0.1761951
+294,Romford Market,51.5790739,0.1813886
+294,Romford Market,51.5790739,0.1813886
+294,Romford Station,51.57472449999999,0.1826519
+294,Gidea Park Station,51.5792473,0.2076649
+294,Harold wood,51.5910397,0.2328613
+294,"Harold Wood, Gooshays Drive",51.6081419,0.2227947
+294,Noak Hill,51.6218055,0.2263263
+295,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+295,Latimer Road Station,51.5134548,-0.2177014
+295,Shepherd's Bush,51.5051913,-0.22469
+295,Brook Green,51.4963863,-0.2217637
+295,Hammersmith,51.491187,-0.223731
+295,Fulham Broadway,51.4802664,-0.1966965
+295,Fulham Broadway,51.4802664,-0.1966965
+295,"Wandsworth Bridge, South Side",51.4651939,-0.1880094
+295,Clapham Junction,51.4651737,-0.1708113
+296,Romford Station,51.57472449999999,0.1826519
+296,Romford Market,51.5790739,0.1813886
+296,Romford North Street Bus Garage,51.5823836,0.1761951
+296,Marks Gate,51.5901971,0.1424532
+296,Little Heath,51.583227,0.120603
+296,Newbury Park,51.5734779,0.08897669999999999
+296,Gants Hill,51.5767812,0.0661732
+296,Ilford Broadway,51.4582445,0.1341027
+296,Ilford Broadway,51.4582445,0.1341027
+297,"Willesden, Bus Garage",51.5474482,-0.2394372
+297,"Neasden, Shopping Centre",51.5626819,-0.2536987
+297,Brent Town Hall,51.5665579,-0.2736435
+297,Wembley Park,51.5585935,-0.2796126
+297,Wembley Central,51.55214429999999,-0.2965274
+297,"Alperton, Sainsbury's",51.5383862,-0.3028583
+297,Perivale Station,51.53667979999999,-0.3237969
+297,"West Ealing, Scotch Common",51.5248572,-0.3210551
+297,Ealing Broadway,51.514042,-0.3015746
+298,Arnos Grove,51.619799,-0.1296871
+298,Southgate,51.62476119999999,-0.1240456
+298,Cockfosters,51.647851,-0.151255
+298,Potters Bar Station,51.6972971,-0.1923315
+298,"Potters Bar, Cranborne Road",51.4309209,-0.0936496
+299,Muswell Hill,51.5911816,-0.1443015
+299,Bounds Green,51.6086813,-0.1274673
+299,Southgate,51.62476119999999,-0.1240456
+299,Cockfosters,51.647851,-0.151255
+300,East Ham Station,51.5393698,0.0510659
+300,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+300,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+300,Beckton Alps,51.5192628,0.0612645
+300,Beckton Station,51.4309209,-0.0936496
+300,Prince Regent,51.5178274,0.0321034
+300,"Plaistow, Greengate Street",51.527444,0.027621
+300,"Plaistow, Balaam Street",51.529212,0.0243676
+300,"Canning Town, Barking Road",51.5208364,0.0191093
+300,Canning Town,51.5189494,0.0132
+302,Mill Hill Broadway,51.6129292,-0.2487871
+302,Burnt Oak,51.602809,-0.266965
+302,Burnt Oak,51.602809,-0.266965
+302,Kingsbury Green,51.5814409,-0.2619577
+302,"Neasden, Shopping Centre",51.5626819,-0.2536987
+302,"Willesden, Bus Garage",51.5474482,-0.2394372
+302,Kensal Rise,51.5345071,-0.2250186
+303,Edgware,51.61548819999999,-0.2609598
+303,Mill Hill Broadway,51.6129292,-0.2487871
+303,Mill Hill Broadway,51.6129292,-0.2487871
+303,Grahame Park,51.6017283,-0.2444205
+303,"Colindale, Superstores",51.5942575,-0.2607018
+305,Edgware,51.5215981,-0.1726091
+305,Burnt Oak,51.4484998,0.0997395
+305,Burnt Oak,51.4484998,0.0997395
+305,Burnt Oak,51.4484998,0.0997395
+305,Kingsbury Circle,51.5850061,-0.2814251
+307,Brimsdown,51.65642219999999,-0.0272713
+307,"Southbury, Great Cambridge Road",51.6492397,-0.0591129
+307,Enfield,51.6622909,-0.1180651
+307,Oakwood,51.6481224,-0.1309298
+307,New Barnet,51.649276,-0.176187
+307,"Barnet, Odeon",51.64663059999999,-0.1865655
+307,Barnet Hospital,51.6508236,-0.2137361
+308,Wanstead,51.5767971,0.0249881
+308,Wanstead Park,51.568725,0.0433573
+308,Stratford,51.5426313,-0.0010369
+308,Stratford City,51.5440354,-0.0053088
+308,Homerton Hospital,51.5478609,-0.0425903
+308,Clapton Pond,51.5561061,-0.05490830000000001
+309,Canning Town,51.5189494,0.0132
+309,Aberfeldy Estate,51.4309209,-0.0936496
+309,"Poplar, All Saints",51.5105521,-0.0118612
+309,"Poplar, Cordelia Street",51.5137347,-0.0174897
+309,Stepney High Street,51.517287,-0.0426262
+309,"Bethnal Green, Chest Hospital",51.53196500000001,-0.0497284
+312,"South Croydon, Bus Garage",51.3544903,-0.0968822
+312,"South Croydon, South End",51.3650199,-0.099012
+312,Croydon Town Centre,51.3769529,-0.0956895
+312,East Croydon,51.3750493,-0.0926978
+312,Lower Addiscombe Road,51.38227269999999,-0.0674548
+312,Ashburton Park,51.3855119,-0.0654191
+312,Norwood Junction,51.39731,-0.07501000000000001
+313,Chingford Station,51.6331421,0.0098588
+313,"Ponders End, Mollison Avenue",51.6792707,-0.0252251
+313,"Ponders End, Bus Garage",51.6452225,-0.04863729999999999
+313,Enfield,51.6522994,-0.0807119
+313,Chase Farm Hospital,51.66689239999999,-0.1028125
+313,Potters Bar Station,51.696636,-0.175948
+313,Dame Alice Owen's School,51.6907953,-0.2071661
+314,Eltham Station,51.45564,0.0525
+314,"Eltham, Footscray Road",51.440054,0.0695436
+314,"Five Ways, Green Lane",51.6193019,-0.1068853
+314,Elmstead Woods,51.42242050000001,0.04166810000000001
+314,Plaistow Green,51.4139535,0.0168425
+314,Bromley North,51.406025,0.013156
+314,Bromley South,51.406025,0.013156
+314,Hayes Station,51.37633599999999,0.010589
+314,Coney Hall,51.3711435,-0.0014082
+314,Addington Village,51.358673,-0.0312539
+314,New Addington,51.348184,-0.017094
+315,West Norwood,51.427905,-0.1002486
+315,"Streatham, St Leonards Church",51.42926610000001,-0.1311095
+315,"Streatham, St. Leonard's Church",51.42926610000001,-0.1311095
+315,Balham,51.4439889,-0.1494105
+316,Cricklewood Bus Garage,51.5581887,-0.2163581
+316,Cricklewood Broadway,51.5595363,-0.2184213
+316,Kilburn High Road Station,51.537243,-0.192318
+316,Kilburn Park,51.53504119999999,-0.1938988
+316,Queen's Park,51.5345448,-0.2043853
+316,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+316,North Kensington,51.5246698,-0.2138884
+316,White City,51.51146199999999,-0.2376332
+317,Waltham Cross,51.68584389999999,-0.0330964
+317,St Ignatius College,51.6739451,-0.0549748
+317,Carterhatch,51.66345949999999,-0.0658526
+317,"Southbury, Dearsley Road",51.64991610000001,-0.06317049999999999
+317,Enfield,51.6522994,-0.0807119
+318,North Middlesex Hospital,51.6131618,-0.0735832
+318,Northumberland Park,51.6024517,-0.0676958
+318,"Tottenham, Town Hall",51.5872187,-0.0725467
+318,Stamford Hill,51.5696514,-0.0750199
+319,"Streatham Hill, Telford Avenue",51.4421746,-0.1300019
+319,Streatham Hill Station,51.4307467,-0.1294977
+319,"Streatham, St Leonards Church",51.42926610000001,-0.1311095
+319,Tooting Bec,51.436753,-0.1618404
+319,Tooting Bec,51.436753,-0.1618404
+319,Clapham Junction,51.4651737,-0.1708113
+319,Clapham Junction,51.4651737,-0.1708113
+319,"Battersea, Latchmere Road",51.4646957,-0.161959
+319,"Battersea Bridge, South Side",51.4811674,-0.1725411
+319,"Chelsea, Beaufort Street",51.4846097,-0.1758684
+319,Sloane Square,51.4927684,-0.1570174
+320,Biggin Hill Valley,51.312059,0.032802
+320,Biggin Hill Airport,51.3317877,0.0287812
+320,"Bromley Common, Crown Lane",51.3895022,0.0355797
+320,Bromley South,51.406025,0.013156
+320,Bromley North,51.406025,0.013156
+320,"Downham, Bromley Road",51.4307442,-0.0152414
+320,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+320,Catford Bridge,51.4448458,-0.0247399
+321,"Foots Cray, Tesco",51.4127689,0.121733
+321,Foots Cray,51.4174447,0.1210622
+321,"Sidcup, Police Station",51.4336673,0.1024815
+321,"Eltham, High Street",51.45091499999999,0.0633415
+321,Eltham Church,51.4506338,0.0570862
+321,Eltham Green,51.4533383,0.0356381
+321,Lewisham Station,51.4652098,-0.0131213
+321,New Cross,51.4769047,-0.0336897
+321,New Cross Gate,51.4749904,-0.0403466
+322,Crystal Palace,51.4197233,-0.0830638
+322,Gipsy Hill,51.4238202,-0.0835265
+322,West Norwood,51.427905,-0.1002486
+322,Tulse Hill Station,51.43986,-0.10505
+322,Herne Hill,51.4609208,-0.0985404
+322,Herne Hill,51.4609208,-0.0985404
+322,Brixton,51.4612794,-0.1156148
+322,Clapham North,51.4658813,-0.1413263
+322,Clapham Common,51.4589252,-0.1493071
+323,Canning Town,51.5189494,0.0132
+323,East London Mail Centre,51.55633,0.0655092
+323,Mile End,51.52354529999999,-0.0330122
+324,Stanmore Station,51.617676,-0.311451
+324,Queensbury Station,51.5942132,-0.2853683
+324,Kingsbury,51.5853499,-0.2782546
+324,Colindale,51.5896908,-0.2491029
+324,Hendon Central,51.583202,-0.226399
+324,Brent Cross,51.5763589,-0.2236956
+324,"Brent Cross, Tesco",51.5741621,-0.2146762
+325,"East Beckton, Sainsbury's",51.5212249,0.0669226
+325,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+325,East Ham Station,51.5393698,0.0510659
+325,"East Ham, Plashet Grove",51.5395772,0.0460004
+325,"Forest Gate, Police Station",51.5467822,0.0309995
+325,"Plaistow, Broadway",51.529163,0.024332
+325,Plaistow Abbey Arms,51.5222296,0.0225853
+325,Prince Regent,51.4309209,-0.0936496
+326,"Barnet, The Spires",51.655492,-0.2033422
+326,Barnet Church,51.6526856,-0.1992227
+326,New Barnet,51.649276,-0.176187
+326,Dollis Valley,51.5957933,-0.209576
+326,Totteridge & Whetstone,51.630241,-0.179144
+326,"Finchley, Church End",51.604606,-0.1882833
+326,Hendon Central,51.583202,-0.226399
+326,Brent Cross,51.5763589,-0.2236956
+327,Waltham Cross,51.68584389999999,-0.0330964
+327,Elsinge Estate,51.6793634,-0.04655339999999999
+328,Golders Green,51.5740013,-0.1987725
+328,"Finchley Road, Hendon Way",51.5824058,-0.2269962
+328,West Hampstead,51.5490183,-0.1971205
+328,"Kilburn, Quex Road",51.5404545,-0.1937492
+328,Kilburn High Road Station,51.537243,-0.192318
+328,Kilburn Park,51.53504119999999,-0.1938988
+328,"Maida Hill, The Chippenham",51.5243627,-0.2017331
+328,Westbourne Park,51.51769299999999,-0.194941
+328,Westbourne Park,51.51769299999999,-0.194941
+328,Notting Hill Gate,51.5086878,-0.2005318
+328,"Kensington, High Street",51.4976157,-0.2037023
+328,"Kensington, Cromwell Road",51.4949065,-0.1953115
+328,Earl's Court,51.490331,-0.1958417
+328,"Chelsea, Redcliffe Gardens",51.4867031,-0.1875171
+328,"Chelsea, World's End",51.4810423,-0.1786311
+328,"Chelsea, World's End",51.4810423,-0.1786311
+329,Enfield,51.6522994,-0.0807119
+329,Winchmore Hill,51.6320279,-0.09580219999999999
+329,Winchmore Hill,51.6320279,-0.09580219999999999
+329,"Palmers Green, Hedge Lane",51.6173228,-0.0874008
+329,"Palmers Green, North Circular Road",51.6122666,-0.1091537
+329,Wood Green,51.5971722,-0.1098021
+329,Wood Green,51.5971722,-0.1098021
+330,Wanstead Park Station,51.551239,0.0251455
+330,"Forest Gate, Police Station",51.5467822,0.0309995
+330,Upton Park Station,51.5353424,0.0352766
+330,"Upton Park, Boleyn",51.5305005,0.0384915
+330,"Plaistow, Balaam Street",51.529212,0.0243676
+330,"Canning Town, Barking Road",51.521274,0.0207211
+330,Canning Town,51.5189494,0.0132
+331,Ruislip,51.5758719,-0.421236
+331,Ruislip Lido,51.59114049999999,-0.4304918
+331,Northwood Station,51.6112297,-0.423889
+331,Mount Vernon Hospital,51.6153975,-0.4455072
+331,Uxbridge,51.5485,-0.479611
+332,"Brent Park, Superstores",51.55263000000001,-0.2568869
+332,"Neasden, Shopping Centre",51.5626819,-0.2536987
+332,Cricklewood Bus Garage,51.56195959999999,-0.2224221
+332,Cricklewood Broadway,51.5597831,-0.2188271
+332,Kilburn High Road Station,51.537243,-0.192318
+332,Kilburn High Road Station,51.537243,-0.192318
+332,Edgware Road Station,51.51988249999999,-0.1678336
+332,Paddington,51.515973,-0.174943
+333,Tooting Broadway,51.427867,-0.1678142
+333,"Streatham, St. Leonard's Church",51.42926610000001,-0.1311095
+333,"Streatham Hill, Telford Avenue",51.4421746,-0.1300019
+333,"Brixton Hill, Christchurch Road",51.4458253,-0.124245
+333,Stockwell,51.4647668,-0.1144344
+333,Brixton,51.4722042,-0.1127279
+333,Brixton,51.4722042,-0.1127279
+333,Kennington Church,51.50875809999999,-0.1954048
+333,Elephant & Castle,51.4938058,-0.0977932
+336,Catford Bridge,51.4448458,-0.0247399
+336,Downham,51.4243854,0.0122988
+336,Plaistow Green,51.4139535,0.0168425
+336,"Bromley Common, Bus Garage",51.38774,0.0363217
+336,Bromley North,51.40833,0.01702
+336,Bromley South,51.406025,0.013156
+336,Bickley,51.38994700000001,0.0492904
+336,Locksbottom,51.3673231,0.0547259
+337,Clapham Junction,51.4651737,-0.1708113
+337,Wandsworth,51.45837299999999,-0.1891356
+337,Putney Station,51.4611807,-0.2164913
+337,Putney Station,51.4611807,-0.2164913
+337,Putney Station,51.4611807,-0.2164913
+337,Barnes Common,51.4681254,-0.2413995
+337,"East Sheen, Queen's Road",51.4663301,-0.2595362
+337,Richmond,51.46131099999999,-0.303742
+339,Leytonstone,51.5649624,0.0088141
+339,Stratford City,51.5440354,-0.0053088
+339,"Thatched House, Crownfield Road",51.5511521,-0.0040387
+339,"Bow, Fish Island",51.5363622,-0.0238479
+339,Mile End,51.52354529999999,-0.0330122
+339,Shadwell,51.51450620000001,-0.05711619999999999
+340,Edgware,51.61548819999999,-0.2609598
+340,Stanmore Broadway,51.6176414,-0.3095879
+340,Harrow Weald Bus Garage,51.6064297,-0.3405434
+340,Harrow,51.580559,-0.341995
+341,"Angel Road, Superstores",51.6130441,-0.0522623
+341,Northumberland Park,51.6024517,-0.0676958
+341,"Tottenham, Town Hall",51.5872187,-0.0725467
+341,West Green,51.586254,-0.0867628
+341,"Harringay, Salisbury Road",51.5814632,-0.0989471
+341,Newington Green,51.5514507,-0.0857535
+341,Islington Angel,51.5346761,-0.1042905
+341,Rosebery Avenue,51.5299565,-0.1055196
+341,Holborn Circus,51.5177959,-0.1075978
+341,Aldwych,51.5132441,-0.1172819
+341,Waterloo,51.5048541,-0.1136621
+343,City Hall,51.4309209,-0.0936496
+343,Elephant & Castle,51.4938058,-0.0977932
+343,Peckham,51.47032369999999,-0.0673872
+343,Peckham Rye,51.4657456,-0.0660497
+343,Brockley,51.46377160000001,-0.0366031
+343,New Cross Gate,51.4749904,-0.0403466
+344,Clapham Junction,51.4651737,-0.1708113
+344,Nine Elms,51.4801974,-0.1396819
+344,Vauxhall,51.4861671,-0.12172
+344,Elephant & Castle,51.4938058,-0.0977932
+344,London Bridge,51.5078788,-0.0877321
+344,Liverpool Street,51.5175001,-0.0826966
+345,Peckham,51.47032369999999,-0.0673872
+345,Camberwell Green,51.4748827,-0.0921158
+345,Brixton,51.4612794,-0.1156148
+345,Clapham Common,51.4589252,-0.1493071
+345,Clapham Junction,51.4651737,-0.1708113
+345,"Battersea, Latchmere Road",51.4646957,-0.161959
+345,"Battersea Bridge, South Side",51.4811674,-0.1725411
+345,South Kensington,51.4953291,-0.1789909
+346,Upminster Station,51.5589642,0.2506216
+346,Upminster Park Estate,51.570667,0.26893
+347,Romford Station,51.57472449999999,0.1826519
+347,Upminster,51.55591399999999,0.248894
+347,Ockendon,51.5444086,-0.0888143
+349,"Ponders End, Bus Garage",51.6452225,-0.04863729999999999
+349,Edmonton Green,51.6248126,-0.0581806
+349,Edmonton Green,51.6248126,-0.0581806
+349,"Angel, Edmonton",51.6100108,-0.0474714
+349,"Snells Park, Sainsburys",51.609054,-0.0691713
+349,"Tottenham, Town Hall",51.5872187,-0.0725467
+349,Stamford Hill,51.5696514,-0.0750199
+350,"Hayes, Asda",51.5010485,-0.4251519
+350,Stockley Park,51.5119958,-0.4500708
+350,West Drayton,51.502985,-0.4654099999999999
+350,West Drayton,51.502985,-0.4654099999999999
+350,Harmondsworth,51.487453,-0.475554
+350,Heathrow Terminal 5,51.471466,-0.4879806
+352,Bromley North,51.40833,0.01702
+352,"Beckenham, War Memorial",51.406914,-0.0320175
+352,Beckenham Junction,51.4109588,-0.0258909
+352,Lower Sydenham,51.42603219999999,-0.0325314
+353,Ramsden Estate,51.3754771,0.1224719
+353,"Orpington, Walnuts Centre",51.3773656,0.1007092
+353,"Orpington, Perry Hall Road",51.3823992,0.0998353
+353,Locksbottom,51.3673231,0.0547259
+353,Hayes Station,51.37633599999999,0.010589
+353,Forestdale,51.345018,-0.0380398
+354,Penge,51.41388490000001,-0.0570112
+354,"Beckenham, War Memorial",51.406914,-0.0320175
+354,Beckenham Junction,51.4109588,-0.0258909
+354,Bromley North,51.406025,0.013156
+355,Mitcham,51.402869,-0.166709
+355,Mitcham,51.402869,-0.166709
+355,Tooting Station,51.41986989999999,-0.16136
+355,Tooting Broadway,51.427867,-0.1678142
+355,Tooting Bec,51.436753,-0.1618404
+355,Tooting Bec,51.436753,-0.1618404
+355,Balham,51.4439889,-0.1494105
+355,Clapham Park,51.4476066,-0.1431943
+355,Brixton,51.4612794,-0.1156148
+356,Upper Sydenham,51.43066,-0.071188
+356,Forest Hill,51.4397781,-0.0546416
+356,Lower Sydenham,51.42603219999999,-0.0325314
+356,Elmers End Green,51.3987339,-0.0436577
+356,Shirley,51.3751931,-0.0488993
+357,Chingford Hatch,51.61703,-0.000263
+357,Chingford Mount,51.6185735,-0.0180318
+357,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+357,Walthamstow Central,51.5830128,-0.019886
+357,Whipps Cross,51.581499,0.0001219
+357,Whipps Cross Hospital,51.5778196,0.0032545
+358,Orpington Station,51.37329,0.08911999999999999
+358,"Orpington, Walnuts Centre",51.3773656,0.1007092
+358,Green Street Green,51.3535363,0.0890088
+358,Locksbottom,51.3673231,0.0547259
+358,Bromley South,51.406025,0.013156
+358,Bromley North,51.406025,0.013156
+358,"Bromley Common, Crown Lane",51.3895022,0.0355797
+358,Park Langley,51.385466,-0.0087119
+358,Elmers End,51.39749,-0.0474767
+358,"Beckenham, War Memorial",51.406914,-0.0320175
+358,Penge,51.41388490000001,-0.0570112
+358,Crystal Palace,51.4197233,-0.0830638
+359,Purley,51.339228,-0.119711
+359,Addington Village,51.358673,-0.0312539
+360,Elephant & Castle,51.4938058,-0.0977932
+360,Vauxhall,51.4861671,-0.12172
+360,Pimlico,51.490744,-0.1403619
+360,Sloane Square,51.4927684,-0.1570174
+360,South Kensington,51.4953291,-0.1789909
+360,Royal Albert Hall,51.5009088,-0.177366
+362,Grange Hill,51.4309209,-0.0936496
+362,"Hainault, The Lowe",51.6099517,0.1092883
+362,Marks Gate,51.5901971,0.1424532
+362,Chadwell Heath,51.5722283,0.141995
+362,Little Heath,51.583227,0.120603
+362,King George Hospital,51.5802748,0.1115243
+363,Crystal Palace,51.4197233,-0.0830638
+363,Upper Sydenham,51.43066,-0.071188
+363,Honor Oak,51.4489977,-0.0457341
+363,Peckham Rye,51.4657456,-0.0660497
+363,Peckham,51.47032369999999,-0.0673872
+363,Bricklayer's Arms,51.4661409,-0.2174147
+363,Elephant & Castle,51.4938058,-0.0977932
+364,Ilford,51.556619,0.076251
+364,Ilford Broadway,51.5584078,0.07077839999999999
+364,Bennett's Castle Lane,51.5514521,0.1235038
+364,Goodmayes,51.5662262,0.1102974
+364,Dagenham East,51.5402631,0.1482103
+365,Orchard Village,51.5296853,0.1699365
+365,"South Hornchurch, Cherry Tree Lane",51.5288841,0.1890788
+365,Elm Park,51.548497,0.1999531
+365,Roneo Corner,51.5654177,0.1885364
+365,Roneo Corner,51.5654177,0.1885364
+365,Romford Station,51.57472449999999,0.1826519
+365,Romford Market,51.5790739,0.1813886
+365,"Romford, Parkside Avenue",51.5908267,0.1816681
+365,"Romford, Queens Hospital",51.5688117,0.1807796
+365,Collier Row,51.5996927,0.1745949
+365,Havering Park,51.607707,0.157121
+366,Redbridge,51.5748179,0.0507539
+366,Redbridge Station,51.5763264,0.0453986
+366,Ilford,51.556619,0.076251
+366,"Barking, London Road",51.5738007,0.1543557
+366,"East Beckton, Sainsbury's",51.5212249,0.0669226
+366,Gallions Reach Station,51.5090228,0.07172769999999999
+366,Gallions Reach Shopping Park,51.5166002,0.0783827
+366,Beckton Station,51.5144016,0.06153319999999999
+367,West Croydon,51.368451,-0.09966350000000002
+367,East Croydon,51.3769529,-0.0956895
+367,Monks Orchard,51.385291,-0.037641
+367,Elmers End,51.39749,-0.0474767
+367,Beckenham Junction,51.4109588,-0.0258909
+367,"Beckenham, High Street",51.40687,-0.0318188
+367,Bromley South,51.406025,0.013156
+367,Bromley North,51.406025,0.013156
+368,Chadwell Heath,51.5722283,0.141995
+368,Bennett's Castle Lane,51.5514521,0.1235038
+368,"Lodge Avenue, Ripple Road",51.53554829999999,0.0936497
+368,Barking,51.536563,0.075766
+368,"Barking, Harts Lane",51.5414506,0.0726712
+370,Romford Market,51.5790739,0.1813886
+370,Romford Station,51.57472449999999,0.1826519
+370,Hornchurch Town Centre,51.562254,0.218605
+370,Upminster,51.55591399999999,0.248894
+370,Corbets Tey,51.543329,0.2505335
+370,Lakeside,51.4309209,-0.0936496
+371,Kingston,51.41233,-0.300689
+371,"Kingston Hill, Queens Road",51.4386928,-0.2909764
+371,Ham,51.4299232,-0.2984002
+371,Richmond Hill,51.4539315,-0.2997198
+371,Richmond,51.46131099999999,-0.303742
+371,"Richmond, Manor Circus",51.4677844,-0.2883524
+372,Hornchurch Town Centre,51.562254,0.218605
+372,Elm Park,51.548497,0.1999531
+372,Rainham Tesco,51.5200061,0.1907802
+372,Averley,51.499018,0.2519159
+372,Wennington,51.5075862,0.2137575
+372,Lakeside,51.403305,-0.0200916
+375,Romford Station,51.57472449999999,0.1826519
+375,Passingford Bridge,51.656024,0.168335
+376,Beckton Station,51.5144016,0.06153319999999999
+376,Winsor Park,51.4818292,-0.4225758
+376,Cyprus,51.5091192,0.0633823
+376,Newham Hospital,51.5222415,0.0325405
+376,"Upton Park, Boleyn",51.5305005,0.0384915
+376,Upton Park Station,51.5353424,0.0352766
+376,"East Ham, Plashet Grove",51.540111,0.0488804
+376,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+377,"Ponders End, Bus Garage",51.6452225,-0.04863729999999999
+377,Bush Hill Park,51.6445559,-0.06559659999999999
+377,Bush Hill Park,51.6445559,-0.06559659999999999
+377,Enfield,51.6522994,-0.0807119
+377,Oakwood,51.6481224,-0.1309298
+379,Chingford Station,51.6331421,0.0098588
+379,Yardley Lane,51.6418904,-0.0087819
+380,Belmarsh,51.4967407,0.0927968
+380,Broadwater Estate,51.5944339,-0.0812275
+380,Plumstead Station,51.4896774,0.0847463
+380,Woolwich,51.4894752,0.06758829999999999
+380,Woolwich,51.4894752,0.06758829999999999
+380,Charlton Village,51.4900403,0.0307737
+380,"Blackheath, Royal Standard",51.4779946,0.0202001
+380,Blackheath Village,51.4657729,0.0091238
+380,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+381,Peckham,51.47032369999999,-0.0673872
+381,Surrey Quays,51.4944172,-0.0383063
+381,Canada Water,51.4962989,-0.0482742
+381,Rotherhithe,51.49628999999999,-0.0411931
+381,Rotherhithe,51.49628999999999,-0.0411931
+381,"Tower Bridge Road, Druid Street",51.4996634,-0.07507899999999999
+381,Southwark Bridge Road,51.4968084,-0.1000501
+381,Waterloo,51.5048541,-0.1136621
+382,Southgate,51.62476119999999,-0.1240456
+382,Arnos Grove,51.619799,-0.1296871
+382,Hampden Square,51.6323276,-0.1417747
+382,Friern Barnet,51.6141967,-0.1540148
+382,Finchley Central,51.601633,-0.193361
+382,Millbrook Park,51.6112324,-0.2073392
+383,"Barnet, The Spires",51.655492,-0.2033422
+383,Barnet Church,51.6526856,-0.1992227
+383,New Barnet,51.649276,-0.176187
+383,Oakleigh Park,51.62524879999999,-0.1697717
+383,Totteridge & Whetstone,51.630241,-0.179144
+383,Woodside Park,51.6162352,-0.1874339
+384,"Barnet, Quinta Drive",51.6467413,-0.2233541
+384,Barnet Hospital,51.6508236,-0.2137361
+384,"Barnet, The Spires",51.655492,-0.2033422
+384,Barnet Church,51.6526856,-0.1992227
+384,"Barnet, Odeon",51.64663059999999,-0.1865655
+384,New Barnet Station,51.64857,-0.17297
+384,"New Barnet, Castlewood Road",51.6540941,-0.16659
+384,Cockfosters,51.647851,-0.151255
+385,Chingford Station,51.6331421,0.0098588
+385,"Crooked Billet, Sainsbury's",51.601088,-0.0159737
+386,Woolwich,51.4894752,0.06758829999999999
+386,Queen Elizabeth Hospital,51.4778139,0.0505587
+386,"Blackheath, Royal Standard",51.4779946,0.0202001
+386,"Woolwich Road, Vanbrugh Hill",51.48505249999999,0.0081975
+386,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+386,Blackheath Village,51.4657729,0.0091238
+388,Stratford City,51.5440354,-0.0053088
+388,Hackney Wick,51.544579,-0.0256935
+388,"South Hackney, Church Crescent",51.5882451,-0.1449718
+388,Ash Grove,51.4797615,-0.3899081
+388,Liverpool Street,51.5175001,-0.0826966
+388,St. Paul's,51.5138453,-0.0983506
+388,Blackfriars,51.51199200000001,-0.1038617
+388,Elephant & Castle,51.4938058,-0.0977932
+389,"Barnet, The Spires",51.655492,-0.2033422
+389,"Barnet, Western Way",51.6405093,-0.1874788
+390,Archway,51.4309209,-0.0936496
+390,"Camden Road, Brecknock Road",51.5566952,-0.137981
+390,King's Cross,51.5347488,-0.1245845
+390,Euston,51.5239197,-0.1433825
+390,Warren Street,51.5240516,-0.1399547
+390,Warren Street,51.5240516,-0.1399547
+390,Tottenham Court Road,51.5166043,-0.1304303
+390,Oxford Circus,51.5143582,-0.1510547
+390,Marble Arch,51.5132225,-0.1588937
+390,Marble Arch,51.5132225,-0.1588937
+390,Marble Arch,51.5132225,-0.1588937
+390,Lancaster Gate,51.5115786,-0.1802482
+390,Notting Hill Gate,51.5090534,-0.1966727
+391,Richmond,51.46131099999999,-0.303742
+391,"North Sheen, Manor Circus",51.4653637,-0.2863842
+391,Kew Gardens Station,51.47714509999999,-0.2850662
+391,Chiswick Roundabout,51.4910362,-0.2816861
+391,Turnham Green,51.49203019999999,-0.2663174
+391,"Stamford Brook, Chiswick Lane",51.49492,-0.24568
+391,Stamford Brook Bus Garage,51.493069,-0.2493815
+391,Ravenscourt Park,51.4952687,-0.2397848
+391,Hammersmith,51.491187,-0.223731
+391,"North End Road, Lillie Road",51.4857738,-0.2013501
+391,Fulham Broadway,51.4801685,-0.1968672
+391,"Fulham, Sands End",51.4731566,-0.1822545
+393,Clapton Pond,51.5561061,-0.05490830000000001
+393,Clapton Pond,51.5561061,-0.05490830000000001
+393,Stoke Newington,51.561175,-0.08349229999999999
+393,Albion Road,51.5611171,-0.08349229999999999
+393,Highbury New Park,51.5598259,-0.0919793
+393,Highbury & Islington,51.5569649,-0.0979656
+393,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+393,"Camden Road, Brecknock Road",51.55676690000001,-0.1382933
+393,Kentish Town,51.5516806,-0.1410992
+393,Chalk Farm,51.5444834,-0.152158
+394,Homerton Hospital,51.5478609,-0.0425903
+394,Hackney Central,51.5482344,-0.05738749999999999
+394,Ash Grove,51.4797615,-0.3899081
+394,"Hoxton, Baring Street",51.5368127,-0.0882585
+394,Islington Angel,51.5346761,-0.1042905
+395,Harrow,51.580559,-0.341995
+395,South Harrow,51.5683717,-0.3553483
+395,Northolt,51.546615,-0.373103
+395,"Greenford, Westway Cross",51.5424454,-0.3406048
+396,King George Hospital,51.5802748,0.1115243
+396,Little Heath,51.583227,0.120603
+396,Newbury Park,51.5734779,0.08897669999999999
+396,Gants Hill,51.5767812,0.0661732
+396,Ilford Broadway,51.5584078,0.07077839999999999
+397,"Crooked Billet, Sainsbury's",51.601088,-0.0159737
+397,Chingford Mount,51.6185735,-0.0180318
+397,Chingford Station,51.6331421,0.0098588
+397,Loughton,51.655942,0.068161
+397,Debden,51.5417031,0.2034589
+398,Ruislip,51.5758719,-0.421236
+398,Rayners Lane Station,51.5751034,-0.3708618
+398,South Harrow,51.5683717,-0.3553483
+398,Wood End,51.3486429,-0.1545569
+399,"Barnet, The Spires",51.655492,-0.2033422
+399,Hadley Wood Station,51.668411,-0.1764367
+401,Thamesmead,51.50575809999999,0.1100586
+401,Thamesmead East,51.50575809999999,0.1100586
+401,Belvedere,51.48516499999999,0.14827
+401,Belvedere,51.48516499999999,0.14827
+401,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+403,West Croydon,51.368451,-0.09966350000000002
+403,Croydon Town Centre,51.3769529,-0.0956895
+403,"South Croydon, South End",51.3650199,-0.099012
+403,Sanderstead Church,51.33693299999999,-0.07585349999999999
+403,Warlingham Green,51.3093239,-0.055901
+403,Warlingham,51.3093239,-0.055901
+404,Coulsdon,51.319941,-0.141267
+404,Caterham-on-the-Hill,51.28029600000001,-0.08161589999999999
+405,Redhill,51.4210856,0.0635313
+405,Hooley,51.4309209,-0.0936496
+405,Coulsdon,51.319941,-0.141267
+405,Purley,51.339228,-0.119711
+405,"Purley Way, Colonnades",51.3563828,-0.1135816
+405,"South Croydon, South End",51.3650199,-0.099012
+405,West Croydon,51.368451,-0.09966350000000002
+406,Kingston,51.41233,-0.300689
+406,Kingston,51.41233,-0.300689
+406,Surbiton,51.39400999999999,-0.302662
+406,Tolworth,51.3801004,-0.2861237
+406,Ewell,51.38217210000001,-0.285232
+406,Epsom,51.4309209,-0.0936496
+406,Epsom Hospital,51.3251497,-0.2732057
+407,Sutton Town Centre,51.3614279,-0.193961
+407,Sutton Station,51.3596681,-0.1911606
+407,"Carshalton, High Street",51.365212,-0.1614104
+407,Beddington Library,51.3669545,-0.1318798
+407,West Croydon,51.368451,-0.09966350000000002
+407,Croydon Town Centre,51.3769529,-0.0956895
+407,Croydon Town Centre,51.3769529,-0.0956895
+407,"South Croydon, South End",51.3650199,-0.099012
+407,Purley,51.339228,-0.119711
+407,Purley,51.339228,-0.119711
+407,Whyteleafe,51.3017577,-0.079251
+407,Whyteleafe South,51.3033428,-0.0769221
+407,Caterham,51.28029600000001,-0.08161589999999999
+410,Crystal Palace,51.4197233,-0.0830638
+410,Norwood Junction,51.39731,-0.07501000000000001
+410,Davidson Road,51.3875213,-0.08113229999999999
+410,West Croydon,51.368451,-0.09966350000000002
+410,Beddington Library,51.3669545,-0.1318798
+410,Wallington,51.363978,-0.151845
+411,Kingston,51.4309209,-0.0936496
+411,"Kingston Bridge, West Side",51.4309209,-0.0936496
+411,Hampton Court,51.4036128,-0.3377623
+411,West Molesey,51.400766,-0.3562949
+412,Purley,51.339228,-0.119711
+412,Sanderstead Church,51.33693299999999,-0.07585349999999999
+412,Sanderstead Church,51.33693299999999,-0.07585349999999999
+412,Selsdon,51.34372279999999,-0.061975
+412,"South Croydon, South End",51.3650199,-0.099012
+412,Croydon Town Centre,51.3769529,-0.0956895
+412,West Croydon,51.368451,-0.09966350000000002
+413,"Sutton, Bushey Road",51.3697877,-0.1980526
+413,Lower Morden,51.3893002,-0.2219715
+413,Morden,51.394943,-0.19446
+414,Putney Bridge,51.4669712,-0.2129034
+414,Fulham Palace Road,51.4789858,-0.2177446
+414,Fulham Broadway,51.4799723,-0.1956774
+414,Chelsea & Westminster Hospital,51.4839583,-0.1813397
+414,South Kensington,51.4953291,-0.1789909
+414,Hyde Park Corner,51.5029347,-0.1508562
+414,Marble Arch,51.5132225,-0.1588937
+414,Edgware Road Station,51.51988249999999,-0.1678336
+414,Warwick Avenue,51.5063258,-0.3039068
+414,"Maida Hill, The Chippenham",51.5243627,-0.2017331
+415,Tulse Hill Station,51.43986,-0.10505
+415,Brixton,51.4612794,-0.1156148
+415,Brixton,51.4612794,-0.1156148
+415,Kennington Church,51.50875809999999,-0.1954048
+415,"Old Kent Road, Tesco",51.4854662,-0.0700918
+417,Crystal Palace,51.4197233,-0.0830638
+417,"Norwood, Crown Point",51.4309209,-0.0936496
+417,"Crown Dale, Norwood School",51.4228251,-0.0995052
+417,"Crown Dale, Norwood School",51.4228251,-0.0995052
+417,Streatham Hill Station,51.4382009,-0.1270706
+417,Clapham Park,51.4476066,-0.1431943
+417,Clapham Common,51.4556465,-0.1385544
+418,Kingston,51.41233,-0.300689
+418,Kingston,51.41233,-0.300689
+418,Surbiton,51.39400999999999,-0.302662
+418,Tolworth,51.3801004,-0.2861237
+418,Epsom,51.4309209,-0.0936496
+419,Richmond,51.46131099999999,-0.303742
+419,"Mortlake, High Street",51.4698327,-0.2611355
+419,Hammersmith,51.491187,-0.223731
+422,North Greenwich,51.4859576,0.007494900000000001
+422,East Greenwich,51.4859576,0.007494900000000001
+422,"Blackheath, Royal Standard",51.4779946,0.0202001
+422,Woolwich,51.4894752,0.06758829999999999
+422,Woolwich,51.4894752,0.06758829999999999
+422,Plumstead,51.4873853,0.08650139999999999
+422,"East Wickham, Brampton Road",51.4771799,0.1236485
+422,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+422,"Bexleyheath, Bus Garage",51.46006930000001,0.1534245
+423,"Hounslow, Bus Station",51.4708688,-0.3546457
+423,"Hounslow, Bell Corner",51.468569,-0.3666325
+423,Hounslow Heath,51.4563954,-0.3849625
+423,Hatton Cross,51.4651031,-0.4157165
+423,"Bath Road, Nobel Drive",51.4806378,-0.4287598
+423,"Bath Road, Sipson Road",51.4876827,-0.4558443
+423,"Bath Road, Hatch Lane",51.4816932,-0.475493
+423,Heathrow Terminal 5,51.471466,-0.4879806
+424,Putney Heath,51.4524424,-0.2298485
+424,Putney Station,51.4611807,-0.2164913
+424,Putney High Street,51.4632453,-0.2158717
+424,Putney Bridge,51.4669712,-0.2129034
+424,Hurlingham,51.4701125,-0.2048867
+424,Fulham Broadway,51.4799723,-0.1956774
+424,"Fulham, Craven Cottage",51.47490029999999,-0.2216078
+424,"Fulham, Craven Cottage",51.47490029999999,-0.2216078
+425,Stratford,51.5426313,-0.0010369
+425,Bow Church,51.5287753,-0.0167013
+425,Mile End,51.52354529999999,-0.0330122
+425,"Hackney, Lauriston Road",51.5394045,-0.0455494
+425,Homerton Hospital,51.5478609,-0.0425903
+425,Clapton Pond,51.5561061,-0.05490830000000001
+425,"Clapton, Nightingale Road",51.5589881,-0.0597757
+427,Uxbridge,51.5485,-0.479611
+427,Coney Green,51.534156,-0.4588592
+427,Hayes End,51.5257,-0.4357732
+427,Hayes By-Pass,51.51593,-0.398889
+427,"Southall, Town Hall",51.5113272,-0.3751471
+427,Southall Park,51.5094438,-0.3697251
+427,Ealing Hospital,51.5075205,-0.3465216
+427,Ealing Broadway,51.5146192,-0.3022912
+427,"Acton, High Street",51.5083364,-0.2761329
+428,Erith,51.480818,0.174675
+428,Slade Green,51.4695282,0.1928854
+428,Crayford,51.4501131,0.1822046
+428,Crayford,51.4501131,0.1822046
+428,Dartford,51.44621,0.216872
+428,Dartford,51.44621,0.216872
+428,Darenth Valley Hospital,51.4353592,0.2586714
+428,Bluewater,51.4309209,-0.0936496
+430,"Roehampton, Danebury Avenue",51.4524056,-0.2483895
+430,Roehampton,51.4484339,-0.2397592
+430,Putney High Street,51.4596431,-0.2141257
+430,Putney Bridge,51.4669712,-0.2129034
+430,West Brompton,51.483494,-0.196802
+430,South Kensington,51.4953291,-0.1789909
+432,Brixton,51.4612794,-0.1156148
+432,Tulse Hill Station,51.43986,-0.10505
+432,West Norwood,51.427905,-0.1002486
+432,West Norwood,51.427905,-0.1002486
+432,Crystal Palace,51.4197233,-0.0830638
+432,Anerley Station,51.4121559,-0.06571779999999999
+433,Addington Village,51.358673,-0.0312539
+433,Selsdon,51.34372279999999,-0.061975
+433,East Croydon,51.3769529,-0.0956895
+433,East Croydon,51.3769529,-0.0956895
+433,West Croydon,51.368451,-0.09966350000000002
+434,"Coulsdon, Ridgemount Avenue",51.3140905,-0.1559805
+434,Coulsdon,51.319941,-0.141267
+434,Purley,51.339228,-0.119711
+434,Purley,51.339228,-0.119711
+434,Purley,51.339228,-0.119711
+434,Whyteleafe South,51.3033428,-0.0769221
+436,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+436,Lewisham Station,51.4652098,-0.0131213
+436,"Lewisham, Jerrard Street",51.4653963,-0.0162157
+436,New Cross Gate,51.4749904,-0.0403466
+436,Peckham,51.47032369999999,-0.0673872
+436,Camberwell Green,51.4741388,-0.09304699999999999
+436,Vauxhall,51.4861671,-0.12172
+436,Battersea Park Station,51.47696,-0.14751
+440,Chiswick Power Road,51.4933973,-0.2809573
+440,Turnham Green,51.49203019999999,-0.2663174
+440,"Acton, High Street",51.50850639999999,-0.2770654
+440,"Acton, Horn Lane",51.5193766,-0.2653401
+440,North Acton,51.5219526,-0.2580821
+440,"Park Royal, Asda",51.52781,-0.26989
+440,Stonebridge Park,51.5445824,-0.2608244
+444,Turnpike Lane Station,51.5904278,-0.1027587
+444,Lordship Lane,51.44687709999999,-0.07245370000000001
+444,North Middlesex Hospital,51.6131618,-0.0735832
+444,"Hall Lane, Cork Tree Retail Park",51.6130849,-0.03223
+444,"Angel Road, Eleys Estate",51.6169024,-0.0460262
+444,"Edmonton, Angel",51.6100108,-0.0474714
+444,"Edmonton, Sterling Way",51.6146137,-0.0702872
+444,Chingford Mount,51.6185735,-0.0180318
+444,Chingford Hatch,51.61703,-0.000263
+444,Chingford Station,51.6331421,0.0098588
+450,West Croydon,51.368451,-0.09966350000000002
+450,"Thornton Heath, High Street",51.3976238,-0.0930168
+450,Upper Norwood,51.41376716037048, -0.09204081941649297
+450,Crystal Palace,51.4197233,-0.0830638
+450,"Westwood Hill, Fountain Drive",51.4268086,-0.0652016
+450,Sydenham,51.4267225,-0.0412072
+450,Lower Sydenham,51.42603219999999,-0.0325314
+452,Kensal Rise,51.5345071,-0.2250186
+452,"Ladbroke Grove, Sainsbury's",51.5256365,-0.215718
+452,Notting Hill Gate,51.5090534,-0.1966727
+452,Royal Albert Hall,51.5009088,-0.177366
+452,Knightsbridge,51.4991195,-0.1644394
+452,Sloane Square,51.4927684,-0.1570174
+452,Sloane Square,51.4927684,-0.1570174
+452,Battersea Park Station,51.47696,-0.14751
+452,Queenstown Road Station,51.4749596,-0.1466578
+452,Vauxhall,51.4861671,-0.12172
+453,Deptford Bridge,51.4744304,-0.0224546
+453,New Cross Gate,51.4749904,-0.0403466
+453,"Old Kent Road, Tesco",51.4854662,-0.0700918
+453,Bricklayer's Arms,51.4661322,-0.2166946
+453,Elephant & Castle,51.4938058,-0.0977932
+453,Lambeth North,51.4989177,-0.1121086
+453,Parliament Square,51.5010421,-0.1268514
+453,"Whitehall, Horse Guards",51.5049111,-0.1273704
+453,Piccadilly Circus,51.5099734,-0.13497
+453,Oxford Circus,51.5137535,-0.1539375
+453,Great Portland Street,51.5236775,-0.1441862
+453,Baker Street Station,51.5231548,-0.156863
+453,Marylebone,51.5188746,-0.1498955
+455,"Purley, Old Lodge Lane",51.3156465,-0.1147698
+455,Purley,51.339228,-0.119711
+455,Purley,51.339228,-0.119711
+455,"South Croydon, South End",51.3650199,-0.099012
+455,Croydon Town Centre,51.3769529,-0.0956895
+455,Croydon Town Centre,51.3769529,-0.0956895
+455,West Croydon,51.368451,-0.09966350000000002
+455,Valley Park,51.4309209,-0.0936496
+455,"Beddington, Asda",51.375982,-0.1309075
+455,Beddington Library,51.3669545,-0.1318798
+455,Roundshaw,51.3533066,-0.1269329
+455,Wallington Station,51.36038,-0.15081
+460,"Willesden, Bus Garage",51.5474482,-0.2394372
+460,Cricklewood Broadway,51.5600397,-0.2190578
+460,Golders Green,51.5740013,-0.1987725
+460,"Finchley, Church End",51.604606,-0.1882833
+460,North Finchley,51.6135087,-0.1754198
+462,Limes Farm Estate,51.4309209,-0.0936496
+462,Grange Hill,51.4309209,-0.0936496
+462,"Barkingside, Fullwell Cross",51.59451199999999,0.08571999999999999
+462,Gants Hill,51.5767812,0.0661732
+462,Ilford,51.556619,0.076251
+463,Coulsdon South,51.31583,-0.13786
+463,Clockhouse Farm,51.4309209,-0.0936496
+463,Wallington,51.363978,-0.151845
+463,"Beddington, Asda",51.375982,-0.1309075
+463,Eastfields,51.4076056,-0.1545941
+463,Pollards Hill,51.4000406,-0.1332582
+464,Tatsfield,51.290898,0.02795
+464,Biggin Hill,51.312059,0.032802
+464,New Addington,51.348184,-0.017094
+465,Kingston,51.41233,-0.300689
+465,Hook Junction,51.3751056,-0.3042808
+465,Hook Junction,51.3751056,-0.3042808
+465,Chessington,51.363583,-0.296254
+465,Leatherhead,51.33560139999999,-0.3202492
+465,Dorking,51.232202,-0.332378
+466,Addington Village,51.358673,-0.0312539
+466,"Addiscombe Road, Shirley Road",51.3750364,-0.0761587
+466,Croydon Town Centre,51.3769529,-0.0956895
+466,Croydon Town Centre,51.3769529,-0.0956895
+466,"South Croydon, Bus Garage",51.3544903,-0.0968822
+466,Purley,51.339228,-0.119711
+466,Purley,51.339228,-0.119711
+466,Old Coulsdon,51.298482,-0.114175
+466,"Coulsdon, Lacey Drive",51.2994337,-0.1144192
+466,Caterham-on-the-Hill,51.28029600000001,-0.08161589999999999
+467,Hinchley Wood School,51.37953599999999,-0.3322176
+467,Hook,51.3682509,-0.305081
+467,Copt Gilders,51.35919000000001,-0.29498
+467,Ewell,51.3805035,-0.2803562
+467,Epsom,51.4309209,-0.0936496
+467,Epsom Hospital,51.3251497,-0.2732057
+468,"South Croydon, South End",51.3650199,-0.099012
+468,Croydon Town Centre,51.3769529,-0.0956895
+468,"Thornton Heath, High Street",51.3976238,-0.0930168
+468,Upper Norwood,51.41376716037048, -0.09204081941649297
+468,Tulse Hill Station,51.43986,-0.10505
+468,Herne Hill,51.4609208,-0.0985404
+468,Herne Hill,51.4609208,-0.0985404
+468,Camberwell Green,51.4741388,-0.09304699999999999
+468,Elephant & Castle,51.4938058,-0.0977932
+469,Queen Elizabeth Hospital,51.4778139,0.0505587
+469,Woolwich,51.4894752,0.06758829999999999
+469,Abbey Wood,51.4926116,0.1188182
+469,Belvedere,51.48516499999999,0.14827
+469,Erith,51.480818,0.174675
+470,Colliers Wood,51.41704439999999,-0.1778555
+470,Morden,51.394943,-0.19446
+470,Sutton Town Centre,51.3614279,-0.193961
+470,Sutton Station,51.3596681,-0.1911606
+470,Cheam,51.3619271,-0.2189255
+470,Ewell,51.3812341,-0.2811869
+470,Ewell East,51.3452748,-0.2415609
+470,Epsom,51.4309209,-0.0936496
+472,North Greenwich,51.4859576,0.007494900000000001
+472,Charlton,51.4900403,0.0307737
+472,Charlton,51.4900403,0.0307737
+472,Woolwich,51.4894752,0.06758829999999999
+472,Woolwich,51.4894752,0.06758829999999999
+472,Plumstead Station,51.4896774,0.0847463
+472,"Thamesmead, Boiler House",51.50575809999999,0.1100586
+472,Thamesmead,51.50575809999999,0.1100586
+473,North Woolwich,51.5008658,0.0626916
+473,London City Airport,51.5048437,0.049518
+473,Prince Regent,51.4309209,-0.0936496
+473,"Plaistow, Greengate Street",51.527444,0.027621
+473,Plaistow,51.5268317,0.0308143
+473,Stratford,51.5426313,-0.0010369
+474,"Canning Town, Barking Road",51.52364720000001,0.0258453
+474,Canning Town,51.5189494,0.0132
+474,London City Airport,51.5048437,0.049518
+474,North Woolwich,51.5008658,0.0626916
+474,Cyprus,51.5091192,0.0633823
+474,Beckton Station,51.5144016,0.06153319999999999
+474,Beckton Alps,51.5192628,0.0612645
+474,"East Ham, Central Park",51.5293175,0.0527634
+474,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+474,East Ham,51.5333972,0.04991139999999999
+474,Manor Park,51.550487,0.0514117
+476,Northumberland Park,51.6024517,-0.0676958
+476,"Tottenham, Town Hall",51.5872187,-0.0725467
+476,Stamford Hill,51.5696514,-0.0750199
+476,Stoke Newington,51.561175,-0.08349229999999999
+476,Albion Road,51.5609591,-0.0832395
+476,Newington Green,51.5514507,-0.0857535
+476,Islington Angel,51.5346761,-0.1042905
+476,King's Cross,51.5347488,-0.1245845
+476,Euston,51.5239197,-0.1433825
+481,Kingston,51.41233,-0.300689
+481,Teddington,51.4268694,-0.3338681
+481,"Fulwell, Stanley Road",51.43500909999999,-0.3471814
+481,"Ivybridge, Tesco",51.4309209,-0.0936496
+481,West Middlesex Hospital,51.4734184,-0.3244425
+482,"Southall, Town Hall",51.5113272,-0.3751471
+482,"Southall, The Green",51.5035525,-0.3802476
+482,Convent Way,51.4933467,-0.3886524
+482,Hounslow West,51.469435,-0.3837709
+482,Hatton Cross,51.4651031,-0.4157165
+482,Heathrow Terminal 4,51.4596965,-0.4473622
+482,Heathrow Terminal 5,51.471466,-0.4879806
+483,Ealing Hospital,51.5075205,-0.3465216
+483,Ealing Broadway,51.5146192,-0.3022912
+483,Ealing Broadway,51.5146192,-0.3022912
+483,"Alperton, Sainsbury's",51.5383862,-0.3028583
+483,Alperton,51.539601,-0.2988365
+483,Wembley Stadium Station,51.55418960000001,-0.286004
+483,Northwick Park Hospital,51.5753935,-0.3201711
+483,North Wembley,51.5625616,-0.3175595
+483,Harrow,51.580559,-0.341995
+484,Lewisham Station,51.4652098,-0.0131213
+484,Ladywell,51.45589709999999,-0.0219523
+484,Brockley Cross,51.465303,-0.0363334
+484,Frendsbury Road,51.4602263,-0.0435112
+484,Peckham Rye,51.45848609999999,-0.0541815
+484,East Dulwich,51.4545635,-0.0732101
+484,Camberwell Green,51.4741388,-0.09304699999999999
+485,Hammersmith,51.491187,-0.223731
+485,Barnes Pond,51.4731208,-0.2468688
+485,Putney Common,51.4676836,-0.228221
+485,Wandsworth,51.45837299999999,-0.1891356
+486,North Greenwich,51.4859576,0.007494900000000001
+486,Charlton,51.4900403,0.0307737
+486,Queen Elizabeth Hospital,51.4778139,0.0505587
+486,"Shooters Hill, Eaglesfield Road",51.4668419,0.0810982
+486,"Shooters Hill, Eaglesfield Road",51.4668419,0.0810982
+486,Welling Corner,51.4626258,0.1081541
+486,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+487,South Harrow,51.5683717,-0.3553483
+487,Northolt Park,51.555711,-0.3594899
+487,"Alperton, Sainsbury's",51.5383862,-0.3028583
+487,Hanger Lane Station,51.530061,-0.2929893000000001
+487,North Acton,51.5219526,-0.2580821
+487,North Acton,51.5219526,-0.2580821
+487,Central Middlesex Hospital,51.530944,-0.2690778
+487,Willesden Junction,51.53211630000001,-0.2433689
+488,Bromley-By-Bow Tesco,51.5266315,-0.0097847
+488,Bow Church,51.5287753,-0.0167013
+488,Hackney Wick,51.544579,-0.0256935
+488,Homerton Hospital,51.5478609,-0.0425903
+488,Clapton Pond,51.5561061,-0.05490830000000001
+488,Dalston Junction,51.5459999,-0.0751485
+490,"Richmond, Pools on the Park",51.4650191,-0.306508
+490,Richmond,51.46131099999999,-0.303742
+490,Richmond Bus Station,51.4591284,-0.3044753000000001
+490,Twickenham,51.4453043,-0.3375429
+490,Feltham Station,51.4480215,-0.4090095
+490,"Hanworth, , Apex Corner",51.4369075,-0.3784005
+490,Hatton Cross,51.4651031,-0.4157165
+490,Heathrow Terminal 4,51.4596965,-0.4473622
+490,Heathrow Cargo Area,51.46351809999999,-0.4558444
+490,Heathrow Terminal 5,51.471466,-0.4879806
+491,Waltham Cross,51.68584389999999,-0.0330964
+491,Enfield Island Village,51.66612199999999,-0.015382
+491,Innova Business Park,51.6768385,-0.0221269
+491,"Brimsdown, Suez Road",51.6526403,-0.029266
+491,Edmonton Green,51.6248126,-0.0581806
+491,North Middlesex Hospital,51.6131618,-0.0735832
+492,Sidcup Station,51.4339345,0.1038351
+492,Foots Cray,51.4174447,0.1210622
+492,Bexley Village,51.439933,0.154327
+492,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+492,Crayford,51.4501131,0.1822046
+492,Dartford,51.44621,0.216872
+492,Dartford,51.44621,0.216872
+492,Bluewater,51.4309209,-0.0936496
+493,"Tooting, St George's Hospital",51.42656299999999,-0.1752284
+493,Wimbledon Stadium,51.41833889999999,-0.2206288
+493,Wimbledon,51.41833889999999,-0.2206288
+493,Wimbledon,51.41833889999999,-0.2206288
+493,Wimbledon,51.41833889999999,-0.2206288
+493,Wimbledon Village,51.41833889999999,-0.2206288
+493,Putney Heath,51.4524424,-0.2298485
+493,Barnes Common,51.4681254,-0.2413995
+493,"East Sheen, Queen's Road",51.4663301,-0.2595362
+493,Richmond,51.46131099999999,-0.303742
+493,"Richmond, Manor Circus",51.4677844,-0.2883524
+496,Harold Wood,51.5910397,0.2328613
+496,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
+496,Gallows Corner,51.59188200000001,0.214546
+496,"Gallows Corner, Main Road",51.5922565,0.2142701
+496,Romford Station,51.57472449999999,0.1826519
+496,Romford Market,51.5790739,0.1813886
+496,"Romford, Queen's Hospital",51.5688117,0.1807796
+498,"Romford, Queen's Hospital",51.5688117,0.1807796
+498,Romford Station,51.57472449999999,0.1826519
+498,Harold Wood,51.5910397,0.2328613
+498,Brentwood,51.4309209,-0.0936496
+499,"Gallows Corner, Tesco",51.5922522,0.219687
+499,Romford Market,51.5790739,0.1813886
+499,Romford Station,51.57472449999999,0.1826519
+499,Romford Queens Hospital,51.5688117,0.1807796
+499,Heath Park Estate,51.5664718,0.1367814
+507,Waterloo,51.5048541,-0.1136621
+507,Millbank,51.4917605,-0.1298473
+507,Victoria,51.49554149999999,-0.1435602
+508,Wansted Park,51.568725,0.0433573
+508,Stratford City,51.5440354,-0.0053088
+521,Waterloo,51.5048541,-0.1136621
+521,Aldwych,51.5132441,-0.1172819
+521,Holborn,51.5175802,-0.1145147
+521,St. Paul's,51.5138453,-0.0983506
+521,London Bridge,51.5078788,-0.0877321
+541,Keir Hardie Estate,51.5678758,-0.0607466
+541,Prince Regent,51.4309209,-0.0936496
+549,South Woodford,51.5912671,0.0264721
+549,Buckhurst Hill,51.627572,0.034513
+549,Loughton,51.655942,0.068161
+601,Thamesmead,51.50575809999999,0.1100586
+601,Bexley,51.439933,0.154327
+601,Wilmington Schools,51.4309209,-0.0936496
+601,Wilmington Schools,51.4309209,-0.0936496
+602,Thamesmead,51.50575809999999,0.1100586
+602,Townley Grammar School,51.4505566,0.1410445
+603,Muswell Hill,51.5911816,-0.1443015
+603,Swiss Cottage,51.5425872,-0.1724737
+605,Edgware,51.61548819999999,-0.2609598
+605,Burnt Oak Station,51.6028241,-0.2640713
+605,Mill Hill County High School,51.6301469,-0.2484735
+605,Totteridge & Whetstone Station,51.63030699999999,-0.1782731
+606,Queensbury,51.5942132,-0.2853683
+606,Edgware,51.61548819999999,-0.2609598
+606,Barnet Church,51.6526856,-0.1992227
+606,Totteridge Academy,51.6393804,-0.1997726
+607,Uxbridge,51.5485,-0.479611
+607,Hillingdon Heath,51.5302584,-0.4469482
+607,"Hayes End, Angel Lane",51.5257,-0.4357732
+607,"Southall, Town Hall",51.5113272,-0.3751471
+607,Ealing Hospital,51.5075205,-0.3465216
+607,Ealing Broadway,51.5146192,-0.3022912
+607,"Acton, High Street",51.5083364,-0.2761329
+607,"Acton, High Street",51.5083364,-0.2761329
+607,Acton Vale,51.5065594,-0.2567913
+607,White City,51.51146199999999,-0.2376332
+608,Gallows Corner,51.59188200000001,0.214546
+608,Shenfield High School,51.6383612,0.3294556
+609,Mortlake,51.4687363,-0.2627417
+609,Harrodian School,51.4817443,-0.2469094
+609,Hammersmith,51.491187,-0.223731
+611,East Finchley Schools,51.592468,-0.1664342
+611,Stonebridge Park,51.5445824,-0.2608244
+612,Selsdon,51.34372279999999,-0.061975
+612,Wallington Grammar School,51.3692254,-0.1488237
+613,Glenthorne School,51.38058789999999,-0.2004546
+613,Tolworth,51.3801004,-0.2861237
+616,Edmonton Green,51.6248126,-0.0581806
+616,Winchmore Hill,51.6320279,-0.09580219999999999
+617,Turnpike Lane Station,51.5904278,-0.1027587
+617,St Ignatius College,51.6739451,-0.0549748
+618,Mill Hill Broadway,51.6129292,-0.2487871
+618,Avanti House School,51.60847620000001,-0.3036894
+619,Edgware Station,51.6134923,-0.2753661
+619,Avanti House School,51.60847620000001,-0.3036894
+621,Lewisham Station,51.4652098,-0.0131213
+621,Crown Woods School,51.4538453,0.07588829999999999
+624,Grove Park,51.4329249,0.021203
+624,Crown Woods College,51.4538453,0.07588829999999999
+624,Welling Corner,51.4626258,0.1081541
+625,Plumstead Common,51.4829577,0.07860199999999999
+625,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+626,Finchley Central,51.601633,-0.193361
+626,Dame Alice Owen's School,51.6907953,-0.2071661
+627,Worcester Park,51.38029,-0.24468
+627,Wallington High School,51.3692254,-0.1488237
+628,"Kingsbury, The Mall",51.5853499,-0.2782546
+628,Southgate,51.62476119999999,-0.1240456
+629,Wood Green,51.5971722,-0.1098021
+629,St Ignatius College,51.6739451,-0.0549748
+631,Golders Green,51.5740013,-0.1987725
+631,Henrietta Barnett School,51.5812815,-0.1886809
+632,"Grahame Park, Corner Mead",51.6017283,-0.2444205
+632,Cricklewood Broadway,51.5600397,-0.2190578
+632,Kilburn Park,51.53504119999999,-0.1938988
+633,Coulsdon South,51.31583,-0.13786
+633,Beddington Church,51.3692339,-0.1270687
+634,Muswell Hill,51.5911816,-0.1443015
+634,"Barnet, Arkley Hotel",51.6522231,-0.2204527
+635,St. Paul's School,51.4884697,-0.2387089
+635,Hounslow Bus Station,51.4708688,-0.3546457
+636,Kemnal Technology College,51.4121053,0.1104831
+636,Grove Park,51.4329249,0.021203
+637,Kemnal Technology College,51.4121053,0.1104831
+637,Grove Park,51.4329249,0.021203
+638,Coney Hall,51.3711435,-0.0014082
+638,Bromley South,51.406025,0.013156
+638,Bromley South,51.406025,0.013156
+638,Bromley North,51.406025,0.013156
+638,Grove Park,51.4329249,0.021203
+638,Eltham College,51.43804009999999,0.038777
+638,Beaverwood School,51.418709,0.089561
+638,Kemnal Technology College,51.4121053,0.1104831
+639,"Roehampton, Danebury Avenue",51.4524056,-0.2483895
+639,St John Bosco College,51.4750653,-0.1714743
+640,Bentley Wood School,51.6173654,-0.3323515
+640,South Harrow,51.5683717,-0.3553483
+641,West Molesey,51.400766,-0.3562949
+641,Teddington Schools,51.423413,-0.3112775
+642,West Hendon Broadway,51.5803328,-0.2424749
+642,London Academy,51.6227086,-0.2894634
+643,Brent Cross,51.5763589,-0.2236956
+643,East Finchley Schools,51.592468,-0.1664342
+646,Noak Hill,51.6218055,0.2263263
+646,Cranham,51.5679469,0.2673702
+648,Romford Market,51.5790739,0.1813886
+648,Cranham,51.5679469,0.2673702
+649,"Romford, Parkside Avenue",51.5885038,0.1772523
+649,Campion School,51.5813295,0.2311271
+650,"Romford, Parkside Avenue",51.5885038,0.1772523
+650,Emerson Park School,51.5692864,0.2427946
+651,Romford Station,51.57472449999999,0.1826519
+651,Bower Park School,51.6054757,0.1802434
+652,"Rainham, Abbey Wood Lane",51.5292975,0.2137483
+652,Upminster,51.55591399999999,0.248894
+653,Muswell Hill,51.5911816,-0.1443015
+653,"Kingsbury, The Mall",51.5853499,-0.2782546
+654,Addington Village,51.358673,-0.0312539
+654,Ramsden Estate,51.3754771,0.1224719
+655,Mitcham,51.402869,-0.166709
+655,Raynes Park High School,51.4032764,-0.2394806
+656,Emerson Park School,51.5692864,0.2427946
+656,"Gallows Corner, Tesco",51.5922522,0.219687
+657,"Crooked Billet, Sainsbury's",51.601088,-0.0159737
+657,Bancroft's School,51.6196768,0.0266543
+658,Crown Woods College,51.4538453,0.07588829999999999
+658,Woolwich,51.4894752,0.06758829999999999
+660,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+660,Crown Woods School,51.4538453,0.07588829999999999
+661,Petts Wood,51.389636,0.08195
+661,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+662,Surbiton Station,51.39255679999999,-0.3044465
+662,Holy Cross School,51.3979182,-0.2616608
+663,Thornton Heath Station,51.3985835,-0.1000937
+663,"Purley, Harris Academy",51.353583,-0.1092537
+664,Charles Darwin School,51.3161242,0.0438115
+664,"New Addington, Homestead Way",51.3353819,-0.010778
+665,Surbiton,51.39400999999999,-0.302662
+665,Holy Cross School,51.3979182,-0.2616608
+667,Ilford,51.556619,0.076251
+667,West Hatch School,51.6124802,0.0629344
+669,Thamesmead,51.50575809999999,0.1100586
+669,Erith Station,51.4816474,0.1753649
+669,Cleeve Park School,51.4289531,0.1195632
+670,"Roehampton, Danebury Avenue",51.4524056,-0.2483895
+670,St John Bosco College,51.4750653,-0.1714743
+671,Tiffin Girls' School,51.4251983,-0.3030517
+671,Chessington South,51.3565368,-0.3080208
+672,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+672,Woolwich,51.4894752,0.06758829999999999
+673,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+673,Beckton Station,51.5144016,0.06153319999999999
+674,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
+674,Romford Station,51.57472449999999,0.1826519
+675,St James Street,51.5064993,-0.1393328
+675,Woodbridge School,51.4309209,-0.0936496
+678,Stratford,51.5426313,-0.0010369
+678,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+678,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+678,Beckton Station,51.5144016,0.06153319999999999
+679,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+679,Woodford Wells,51.6148389,0.0281739
+679,Ilford,51.556619,0.076251
+679,Goodmayes,51.5662262,0.1102974
+681,"Hounslow, Bus Station",51.4708688,-0.3546457
+681,Teddington Schools,51.423413,-0.3112775
+683,Friern Barnet,51.6141967,-0.1540148
+683,"Kingsbury, The Mall",51.5853499,-0.2782546
+684,Orpington Station,51.37329,0.08911999999999999
+684,Charles Darwin School,51.3161242,0.0438115
+685,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+685,Selsdon,51.34372279999999,-0.061975
+686,St Edward's School,51.4309209,-0.0936496
+686,Romford Market,51.5790739,0.1813886
+686,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
+686,Romford Station,51.57472449999999,0.1826519
+687,Dagenham Park School,51.5402631,0.1482103
+687,Barking,51.536563,0.075766
+688,Southgate,51.62476119999999,-0.1240456
+688,"Kingsbury, The Mall",51.5853499,-0.2782546
+689,West Croydon,51.3769529,-0.0956895
+689,Monks Orchard,51.385291,-0.037641
+690,West Norwood,51.427905,-0.1002486
+690,Burntwood School,51.4383279,-0.1797715
+692,NO BLIND DESCRIPTION (Departs only),51.4309209,-0.0936496
+692,Winchmore Hill,51.6320279,-0.09580219999999999
+696,"Hayes, Bourne Avenue",51.5026304,-0.438024
+696,Bishop Ramsey School,51.5792096,-0.4080951
+697,"Hayes End, Lansbury Drive",51.537245,-0.423534
+697,Ickenham,51.563966,-0.442299
+698,West Drayton,51.502985,-0.4654099999999999
+698,Ickenham,51.563966,-0.442299
+699,Winchmore Hill,51.6320279,-0.09580219999999999
+699,Southgate,51.62476119999999,-0.1240456
+699,Dame Alice Owen's School,51.6907953,-0.2071661
+965,Riverhill,51.3768604,-0.2692885
+965,"Kingston, Sainsburys",51.4098232,-0.303191
+969,"Whitton, Gladstone Avenue",51.5961721,-0.1019864
+969,Roehampton Vale,51.4388194,-0.2491381
+A10,Uxbridge,51.5485,-0.479611
+A10,Coney Green,51.5979514,-0.0744009
+A10,Stockley Business Park,51.5979514,-0.0744009
+A10,Stockley Park,51.51153850000001,-0.444799
+A10,Heathrow Central,51.5979514,-0.0744009
+B11,"Bexleyheath, Bus Garage",51.45334099999999,0.13822
+B11,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B11,East Wickham,51.474263,0.112381
+B11,East Wickham,51.474263,0.112381
+B11,Abbey Wood,51.4926116,0.1188182
+B11,"Thamesmead, Boiler House",51.50575809999999,0.1100586
+B11,Thamesmead,51.50575809999999,0.1100586
+B12,Erith,51.480818,0.174675
+B12,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B12,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B12,Bexley Village,51.439933,0.154327
+B12,Joydens Wood,51.4269166,0.1566507
+B12,Joydens Wood,51.4269166,0.1566507
+B12,Joydens Wood,51.4269166,0.1566507
+B13,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B13,"Avery Hill Road,Halfway Street",51.4449166,0.0820603
+B13,New Eltham,51.4322522,0.0658314
+B14,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B14,Blendon,51.44663509999999,0.1240471
+B14,Queen Mary's Hospital,51.4556562,-0.2426609
+B14,St. Mary Cray,51.385993,0.113061
+B14,Orpington,51.374843,0.09421399999999999
+B14,Orpington,51.374843,0.09421399999999999
+B14,Orpington Station,51.37329,0.08911999999999999
+B15,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B15,Welling Corner,51.4622529,0.109744
+B15,Welling Corner,51.4622529,0.109744
+B15,Eltham Church,51.4506338,0.0570862
+B15,Horn Park,51.45056599999999,0.029106
+B16,"Bexleyheath, Bus Garage",51.45334099999999,0.13822
+B16,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+B16,Welling Corner,51.4622529,0.109744
+B16,Falconwood,51.4585461,0.0946553
+B16,Eltham High Street,51.4507726,0.0561761
+B16,Eltham Green,51.4533383,0.0356381
+B16,Kidbrooke,51.46199840000001,0.0277477
+C1,Victoria,51.49554149999999,-0.1435602
+C1,Sloane Square,51.4927684,-0.1570174
+C1,"Earl's Court, Tesco",51.490331,-0.1958417
+C1,South Kensington,51.4953291,-0.1789909
+C1,Shepherd's Bush,51.5051913,-0.22469
+C1,White City,51.51146199999999,-0.2376332
+C2,Parliament Hill Fields,51.5594043,-0.151707
+C2,Kentish Town,51.4309209,-0.0936496
+C2,Camden Town,51.52203979999999,-0.1279844
+C2,Camden Town,51.52203979999999,-0.1279844
+C2,Great Portland Street,51.5199714,-0.1426427
+C2,Berkeley Square,51.5098475,-0.1453298
+C2,Hyde Park Corner,51.5029347,-0.1508562
+C2,Victoria,51.49554149999999,-0.1435602
+C3,Clapham Junction,51.4651737,-0.1708113
+C3,"Wandsworth Bridge, South Side",51.4651939,-0.1880094
+C3,Chelsea Harbour,51.476111,-0.1826413
+C3,West Brompton,51.483494,-0.196802
+C3,Earl's Court,51.490331,-0.1958417
+C3,"Earl's Court, Tesco",51.490331,-0.1958417
+C10,Canada Water,51.4962989,-0.0482742
+C10,Rotherhithe,51.49628999999999,-0.0411931
+C10,Elephant & Castle,51.4938058,-0.0977932
+C10,St George's Circus,51.4984377,-0.1045086
+C10,Millbank,51.4917605,-0.1298473
+C10,Tate Britain,51.4910621,-0.1277886
+C10,Pimlico Station,51.4891,-0.13374
+C10,Victoria Coach Station,51.49554149999999,-0.1435602
+C10,Victoria,51.49554149999999,-0.1435602
+C11,Archway,51.5648883,-0.1323808
+C11,Parliament Hill Fields,51.5594043,-0.151707
+C11,Hampstead Heath,51.5608294,-0.1629416
+C11,Swiss Cottage,51.5425872,-0.1724737
+C11,Finchley Road Station,51.5469174,-0.179986
+C11,West Hampstead,51.5490183,-0.1971205
+C11,"Cricklewood, Pennine Drive",51.5645787,-0.2144717
+C11,Brent Cross,51.5763589,-0.2236956
+D3,"Bethnal Green, Bonner Road",51.5320692,-0.0509221
+D3,Whitechapel,51.5148198,-0.0650534
+D3,"Limehouse, Burdett Road",51.5150014,-0.0285662
+D3,Canary Wharf,51.5054306,-0.0235333
+D3,Leamouth,51.512039,0.001899
+D6,Ash Grove,51.5358094,-0.0581907
+D6,Mile End,51.52354529999999,-0.0330122
+D6,"Limehouse, Burdett Road",51.5150014,-0.0285662
+D6,"Poplar, All Saints",51.5123792,-0.0087975
+D6,Blackwall,51.5079838,-0.007195699999999999
+D6,Crossharbour,51.4958465,-0.0145118
+D7,"Poplar, All Saints",51.5123792,-0.0087975
+D7,Cubitt Town,51.497186,-0.009047
+D7,Cubitt Town,51.497186,-0.009047
+D7,Canary Wharf,51.5054306,-0.0235333
+D7,"Limehouse, Burdett Road",51.5150014,-0.0285662
+D7,Mile End,51.52354529999999,-0.0330122
+D8,Stratford,51.5426313,-0.0010369
+D8,Bromley-By-Bow,51.5278208,-0.0128373
+D8,"Poplar, All Saints",51.5123792,-0.0087975
+D8,Canary Wharf,51.5054306,-0.0235333
+D8,Crossharbour,51.4958465,-0.0145118
+E1,Greenford Broadway,51.5279556,-0.3540139
+E1,Drayton Green,51.515364,-0.3257264
+E1,"West Ealing, Sutherland Avenue",51.5165248,-0.3208564
+E1,Ealing Broadway,51.5132537,-0.3043136
+E2,"Brentford, Commerce Road",51.4836006,-0.313864
+E2,"Brentford, County Court",51.4835374,-0.3063676
+E2,West Ealing,51.51141,-0.3180165
+E2,Ealing Broadway,51.5132537,-0.3043136
+E2,"West Ealing, Scotch Common",51.5248572,-0.3210551
+E2,Greenford Broadway,51.5279556,-0.3540139
+E3,Greenford Broadway,51.5279556,-0.3540139
+E3,Hanwell Broadway,51.5066369,-0.3383229
+E3,West Ealing,51.5281483,-0.0205416
+E3,"Acton, Horn Lane",51.5150958,-0.2686528
+E3,"Acton, High Street",51.5071042,-0.270558
+E3,Turnham Green,51.49203019999999,-0.2663174
+E3,"Chiswick, Edensor Road",51.4821173,-0.255696
+E5,"Southall, Toplocks Estate",51.511073,-0.377232
+E5,"Southall, Town Hall",51.5113272,-0.3751471
+E5,Greenford Broadway,51.5279556,-0.3540139
+E5,"Perivale, Medway Estate",51.5364116,-0.3327652
+E5,Perivale Tesco,51.532222,-0.324477
+E6,Greenford Station,51.5255068,0.05870810000000001
+E6,Greenford Broadway,51.5279556,-0.3540139
+E6,"Glencoe Road, Tesco",51.524364,-0.3880442
+E6,"Yeading, Willow Tree Lane",51.52749319999999,-0.3991509
+E6,"Hayes, Grapes",51.5255068,0.05870810000000001
+E6,Hayes & Harlington Station,51.5029848,-0.4203779
+E6,Hayes & Harlington Station,51.5029848,-0.4203779
+E6,Bull's Bridge,51.4999134,-0.4066811
+E7,Ruislip,51.5758719,-0.421236
+E7,Ruislip Gardens,51.5518094,0.0293728
+E7,"Yeading, White Hart",51.536823,-0.389446
+E7,Greenford Broadway,51.5279556,-0.3540139
+E7,"West Ealing, Sutherland Avenue",51.5165248,-0.3208564
+E7,West Ealing Broadway,51.514042,-0.3015746
+E7,Ealing Broadway,51.5146192,-0.3022912
+E8,Hounslow Bell Corner,51.468569,-0.3666325
+E8,Hounslow Bus Station,51.46092179999999,-0.373149
+E8,Isleworth,51.467121,-0.329003
+E8,Brentford Bus Garage,51.4845841,-0.3155602000000001
+E8,"Brentford, County Court",51.4835374,-0.3063676
+E8,"Brentford, County Court",51.4835374,-0.3063676
+E8,Hanwell Broadway,51.5090444,-0.3376352
+E8,Hanwell Broadway,51.5090444,-0.3376352
+E8,West Ealing,51.51141,-0.3180165
+E8,"West Ealing,Scotch Common",51.5248572,-0.3210551
+E8,Ealing Broadway,51.5132537,-0.3043136
+E9,"Yeading, Barnhill Estate",51.52291,-0.3880247000000001
+E9,"Yeading, White Hart",51.536823,-0.389446
+E9,Greenford Broadway,51.5279556,-0.3540139
+E9,"West Ealing, Scotch Common",51.5248572,-0.3210551
+E9,Ealing Broadway,51.5132537,-0.3043136
+E10,"Northolt, Islip Manor",51.5473716,-0.379684
+E10,Smiths Farm,51.5649619,-0.0146911
+E10,Greenford Broadway,51.5279556,-0.3540139
+E10,"West Ealing, Scotch Common",51.5248572,-0.3210551
+E10,Ealing Broadway,51.5146192,-0.3022912
+E11,Greenford Broadway,51.5279556,-0.3540139
+E11,Drayton Green,51.515364,-0.3257264
+E11,West Ealing,51.5728525,0.0176348
+E11,Ealing Broadway,51.5728525,0.0176348
+E11,"Ealing, Warwick Dene",51.507913,-0.2956596
+EL1,Ilford Station,51.556619,0.076251
+EL1,Barking,51.536563,0.075766
+EL1,Barking,51.536563,0.075766
+EL1,"River Road, Waverley Gardens",51.5343317,-0.2891878
+EL1,"River Road, Waverley Gardens",51.5343317,-0.2891878
+EL1,Barking Riverside,51.536563,0.075766
+EL2,Becontree Heath,51.5609465,0.1488995
+EL2,Five Elms,51.3697855,0.0259964
+EL2,Bennett's Castle Lane,51.5562949,0.1276031
+EL2,Barking,51.536563,0.075766
+EL2,Barking,51.536563,0.075766
+EL2,"River Road, Waverley Gardens",51.5343317,-0.2891878
+EL2,"River Road, Waverley Gardens",51.5343317,-0.2891878
+EL2,Dagenham Dock,51.5402631,0.1482103
+EL3,Little Heath,51.583227,0.120603
+EL3,King George Hospital,51.5802748,0.1115243
+EL3,"Goodmayes, Goodmayes Lane",51.5620979,0.1095257
+EL3,Barking,51.536563,0.075766
+EL3,Creekmouth,51.517381,0.102234
+EL3,Barking,51.536563,0.075766
+EL3,Barking Riverside,51.536563,0.075766
+G1,"Streatham, Green Lane",51.4147104,-0.1158693
+G1,"Streatham, St Leonard's Church",51.4307467,-0.1294977
+G1,Tooting Broadway,51.427867,-0.1678142
+G1,Tooting Broadway,51.427867,-0.1678142
+G1,"Tooting, St George's Hospital",51.42656299999999,-0.1752284
+G1,Springfield Hospital,51.4385846,-0.1718014
+G1,Clapham Junction,51.4651737,-0.1708113
+G1,"Battersea, Shaftesbury Estate",51.47220069999999,-0.165547
+H2,Golders Green,51.5740013,-0.1987725
+H3,Golders Green,51.5740013,-0.1987725
+H3,East Finchley,51.592468,-0.1664342
+H9,Harrow,51.580559,-0.341995
+H9,Northwick Park Hospital,51.5753935,-0.3201711
+H9,"Kenton, Library",51.59262649999999,-0.3111454
+H9,Wealdstone,51.5960603,-0.3334858
+H9,Rayners Lane Station,51.5762173,-0.3702536
+H9,North Harrow,51.58412800000001,-0.3644343
+H10,Harrow,51.580559,-0.341995
+H10,Rayners Lane Station,51.5751034,-0.3708618
+H10,Wealdstone,51.5960603,-0.3334858
+H10,"Kenton, Library",51.59262649999999,-0.3111454
+H10,Northwick Park Hospital,51.5753935,-0.3201711
+H10,North Harrow,51.58412800000001,-0.3644343
+H11,Harrow,51.580559,-0.341995
+H11,Pinner,51.595172,-0.378002
+H11,Northwood Hills,51.6004243,-0.4098652
+H11,Northwood Station,51.6112297,-0.423889
+H11,Mount Vernon Hospital,51.6153975,-0.4455072
+H12,Stanmore Station,51.6196885,-0.3031205
+H12,Stanmore Church,51.6164857,-0.3153133
+H12,Harrow Weald Bus Garage,51.606117,-0.3400905
+H12,Pinner,51.595172,-0.378002
+H12,Rayners Lane Station,51.5751034,-0.3708618
+H12,South Harrow,51.5683717,-0.3553483
+H13,"Northwood Hills, St Vincent's",51.6004243,-0.4098652
+H13,Northwood Hills,51.6004243,-0.4098652
+H13,Pinner,51.595172,-0.378002
+H13,Ruislip,51.5758719,-0.421236
+H13,Ruislip,51.5758719,-0.421236
+H13,Ruislip Lido,51.59114049999999,-0.4304918
+H14,Hatch End,51.6104236,-0.370708
+H14,Courtenay Avenue,51.5747587,-0.1682409
+H14,Harrow,51.580559,-0.341995
+H14,Northwick Park Hospital,51.5753935,-0.3201711
+H17,Harrow,51.580559,-0.341995
+H17,Sudbury,51.5556591,-0.3171114
+H17,Sudbury Hill,51.5539267,-0.337085
+H17,Wembley Central,51.550501,-0.3048409
+H18,Harrow,51.580559,-0.341995
+H18,"Harrow Weald, Long Elmes",51.6044001,-0.3401289
+H18,Belmont Circle,51.6010493,-0.3180225
+H19,Harrow,51.580559,-0.341995
+H19,"Harrow Weald, Long Elmes",51.6044001,-0.3401289
+H19,Belmont Circle,51.6010493,-0.3180225
+H20,"Hounslow, Civic Centre",51.4737233,-0.36638
+H20,"Hounslow, Bell Corner",51.468569,-0.3666325
+H20,Whitton Dene,51.4576828,-0.3517485
+H20,"Ivybridge, Tesco",51.4309209,-0.0936496
+H22,Hounslow Bell Corner,51.468569,-0.3666325
+H22,"Hounslow, Bus Station",51.4708688,-0.3546457
+H22,Whitton Dene,51.4576828,-0.3517485
+H22,Hospital Bridge,51.44267,-0.3652385
+H22,Twickenham,51.4453043,-0.3375429
+H22,Richmond,51.46131099999999,-0.303742
+H22,Richmond,51.46131099999999,-0.303742
+H22,"Richmond, Manor Circus",51.4677844,-0.2883524
+H25,Butts Farm,51.4309209,-0.0936496
+H25,"Hanworth, Main Street",51.4489479,-0.3829269
+H25,"Hanworth, Sunbury Way",51.4311625,-0.4003865
+H25,Feltham,51.44414800000001,-0.410772
+H25,Feltham Station,51.4480215,-0.4090095
+H25,Bedfont Green,51.45109910000001,-0.4402292
+H25,Hatton Cross,51.4651031,-0.4157165
+H26,"Feltham, Sparrow Farm",51.4525059,-0.3975703
+H26,Feltham,51.44414800000001,-0.410772
+H26,Lower Feltham,51.436601,-0.426105
+H26,Bedfont Lakes,51.4469846,-0.4441649
+H26,Bedfont Green,51.45109910000001,-0.4402292
+H26,Hatton Cross,51.4651031,-0.4157165
+H28,Bull's Bridge,51.4999134,-0.4066811
+H28,Heston,51.48420170000001,-0.3719867
+H28,"Hounslow, Bus Station",51.4708688,-0.3546457
+H28,Osterly,51.4819722,-0.3494553
+H28,West Middlesex Hospital,51.4734184,-0.3244425
+H28,Osterley Tesco,51.48580430000001,-0.3301428
+H32,Hounslow Bus Station,51.4708688,-0.3546457
+H32,"Hounslow, Bell Corner",51.468569,-0.3666325
+H32,Hounslow West,51.469435,-0.3837709
+H32,Convent Way,51.4945787,-0.3939649
+H32,"Southall, The Green",51.5035525,-0.3802476
+H32,"Southall, Town Hall",51.5113272,-0.3751471
+H37,"Hounslow, Blenheim Centre",51.4706766,-0.3621538
+H37,"Hounslow, Bus Station",51.4708688,-0.3546457
+H37,"Isleworth, Fire Station",51.467121,-0.329003
+H37,"St Margarets, Chertsey Road",51.4567895,-0.3273389
+H37,Richmond,51.4309209,-0.0936496
+H37,"Richmond, Manor Circus",51.4677844,-0.2883524
+H91,Hounslow West,51.469435,-0.3837709
+H91,Osterley Station,51.48103039999999,-0.3519527
+H91,"Great West Road, Syon Lane",51.4832374,-0.326929
+H91,"Great West Road, Ealing Road",51.4913803,-0.3039856
+H91,Chiswick Roundabout,51.4910362,-0.2816861
+H91,Turnham Green,51.49203019999999,-0.2663174
+H91,"Stamford Brook, Chiswick Lane",51.49492,-0.24568
+H91,"Stamford Brook, Bus Garage",51.493069,-0.2493815
+H91,Ravenscourt Park,51.4952687,-0.2397848
+H91,Hammersmith,51.491187,-0.223731
+H98,"Hounslow, Bus Station",51.4708688,-0.3546457
+H98,"Hounslow, Bell Corner",51.468569,-0.3666325
+H98,Hounslow West,51.469435,-0.3837709
+H98,Cranford,51.4720623,-0.4055896
+H98,"Bath Road, Nobel Drive",51.4806378,-0.4287598
+H98,Harlington Corner,51.4809415,-0.434335
+H98,Hayes & Harlington Station,51.5029848,-0.4203779
+H98,"Uxbridge Road, Lansbury Drive",51.52294149999999,-0.422019
+H98,"Hayes, Church End",51.516758,-0.436786
+H98,Hayes End,51.5257,-0.4357732
+K1,New Malden,51.40066299999999,-0.259263
+K1,Malden Manor Station,51.38473639999999,-0.2611812000000001
+K1,Tolworth,51.3801004,-0.2861237
+K1,"Tolworth, Red Lion Road",51.3807794,-0.2901602
+K1,Hook Junction,51.3751056,-0.3042808
+K1,Surbiton Station,51.39255679999999,-0.3044465
+K1,Surbiton,51.39400999999999,-0.302662
+K1,Kingston,51.41233,-0.300689
+K2,Kingston Hospital,51.4148229,-0.2824061
+K2,"Kingston, Cromwell Road",51.4123016,-0.2986358
+K2,Surbiton,51.39400999999999,-0.302662
+K2,Berrylands,51.3922147,-0.2932239
+K2,"Tolworth, Red Lion Road",51.3807794,-0.2901602
+K2,Tolworth Broadway,51.3806898,-0.2823801
+K2,"Chessington, Industrial Estate",51.3681597,-0.2865138
+K2,Hook,51.3682509,-0.305081
+K3,Roehampton Vale,51.4388194,-0.2491381
+K3,Kingston,51.41233,-0.300689
+K3,"Kingston Vale, Robin Hood Way",51.4253374,-0.2551612
+K3,Kingston Hospital,51.4148229,-0.2824061
+K3,Surbiton Station,51.39255679999999,-0.3044465
+K3,Surbiton,51.39400999999999,-0.302662
+K3,Claygate,51.360219,-0.340969
+K3,"Esher, Trinity School",51.369487,-0.365927
+K3,Esher,51.369487,-0.365927
+K4,Kingston Hospital,51.4148229,-0.2824061
+K4,Kingston,51.41233,-0.300689
+K4,Surbiton,51.39400999999999,-0.302662
+K4,Hook Junction,51.3751056,-0.3042808
+K4,"Hook, Bridge Road",51.420021,-0.1940527
+K4,Mansfield Park,51.4309209,-0.0936496
+K5,Ham,51.4299232,-0.2984002
+K5,Kingston,51.41233,-0.300689
+K5,"New Malden, Fountain Roundabout",51.40066299999999,-0.259263
+K5,Raynes Park,51.4084257,-0.2298751
+K5,Morden,51.394943,-0.19446
+P4,Lewisham Station,51.4652098,-0.0131213
+P4,Ladywell,51.45589709999999,-0.0219523
+P4,Brockley Rise,51.4473951,-0.0416563
+P4,"Forest Hill, Horniman Museum",51.4410762,-0.0612925
+P4,Dulwich Village,51.4506584,-0.0855299
+P4,North Dulwich,51.4433257,-0.0675547
+P4,Loughborough Junction,51.4660641,-0.102184
+P4,Brixton,51.4612794,-0.1156148
+P4,Brixton,51.4612794,-0.1156148
+P5,Elephant & Castle,51.4938058,-0.0977932
+P5,Brixton,51.4612794,-0.1156148
+P5,Stockwell,51.4760412,-0.1263271
+P5,Patmore Estate,51.4763262,-0.1396515
+P12,Surrey Quays,51.4944172,-0.0383063
+P12,Canada Water,51.4962989,-0.0482742
+P12,South Bermondsey,51.48697379999999,-0.0537171
+P12,Peckham,51.47032369999999,-0.0673872
+P12,Peckham Rye,51.4603208,-0.0603961
+P12,Brenchley Gardens,51.4530377,-0.0506801
+P12,Brockley Rise,51.4473951,-0.0416563
+P13,Streatham Station,51.4259857,-0.131308
+P13,Streatham Hill Station,51.4382009,-0.1270706
+P13,Tulse Hill Station,51.43986,-0.10505
+P13,East Dulwich,51.4545635,-0.0732101
+P13,Peckham,51.47032369999999,-0.0673872
+P13,New Cross Gate,51.4749904,-0.0403466
+R1,St Paul's Cray,51.396136,0.1103591
+R1,St Mary Cray,51.385993,0.113061
+R1,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R1,Chelsfield Station,51.35728049999999,0.1063505
+R1,Green Street Green,51.3535363,0.0890088
+R2,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R2,Orpington Station,51.37329,0.08911999999999999
+R2,Locksbottom,51.3673231,0.0547259
+R2,Biggin Hill Airport,51.312059,0.032802
+R2,Biggin Hill Valley,51.312059,0.032802
+R3,Princess Royal Hospital,51.3661498,0.05819390000000001
+R3,Petts Wood,51.389636,0.08195
+R3,"Orpington, Perry Hall Road",51.3823992,0.0998353
+R3,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R3,Orpington Station,51.37329,0.08911999999999999
+R4,Pauls Cray Hill,51.385307,0.114227
+R4,Cockmannings,51.3819698,0.1233517
+R4,Ramsden Estate,51.3754771,0.1224719
+R4,"Orpington, Perry Hall Road",51.3823992,0.0998353
+R4,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R4,Orpington Station,51.37329,0.08911999999999999
+R4,Locksbottom,51.3673231,0.0547259
+R4,Princess Royal Hospital,51.3661498,0.05819390000000001
+R5,Orpington Station,51.37329,0.08911999999999999
+R5,Knockholt,51.311086,0.1062
+R6,Orpington Station,51.37329,0.08911999999999999
+R6,St Mary Cray Station,51.3957762,0.1071945
+R7,Chislehurst,51.412626,0.077487
+R7,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R7,Petts Wood,51.389636,0.08195
+R7,"Bickley, Aquila",51.38994700000001,0.0492904
+R7,Chelsfield Village,51.3562794,0.1254019
+R8,Orpington Station.,51.37329,0.08911999999999999
+R8,Biggin Hill,51.312059,0.032802
+R9,Orpington Station,51.37329,0.08911999999999999
+R9,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R9,Ramsden Estate,51.3754771,0.1224719
+R10,Orpington Station,51.37329,0.08911999999999999
+R10,Knockholt,51.311086,0.1062
+R11,Queen Mary's Hospital,51.4556562,-0.2426609
+R11,Foots Cray,51.4174447,0.1210622
+R11,St Marys Cray,51.385993,0.113061
+R11,"Orpington, Walnuts Centre",51.3773656,0.1007092
+R11,Green Street Green,51.3535363,0.0890088
+R68,Kew Retail Park,51.4778962,-0.2791853
+R68,"Richmond, Manor Circus",51.4677844,-0.2883524
+R68,Richmond,51.46131099999999,-0.303742
+R68,Richmond Bus Station,51.4591284,-0.3044753000000001
+R68,Twickenham,51.4453043,-0.3375429
+R68,Teddington,51.4268694,-0.3338681
+R68,Hampton Church,51.4133939,-0.366712
+R68,Hampton Court,51.4036128,-0.3377623
+R70,"Hampton, The Avenue",51.4133939,-0.366712
+R70,"Fulwell, Cock & Bull",51.4331018,-0.3520137
+R70,Twickenham,51.4453043,-0.3375429
+R70,Richmond Bus Station,51.4591284,-0.3044753000000001
+R70,Richmond,51.46131099999999,-0.303742
+R70,"Richmond, Manor Circus",51.4677844,-0.2883524
+R70,Fulwell,51.4331018,-0.3520137
+R70,"Richmond, Manor Circus",51.4677844,-0.2883524
+RB1,Woolwich Pier,51.4894752,0.06758829999999999
+RB1,North Greenwich Pier,51.5022201,0.0091621
+RB1,Westminster Pier,51.4974948,-0.1356583
+RB1X,Woolwich Pier,51.4894752,0.06758829999999999
+RB1X,North Greenwich Pier,51.5022201,0.0091621
+RB1X,Westminster Pier,51.4974948,-0.1356583
+RB2,London Bridge Pier,51.4966529,-0.0299834
+RB2,Bankside,51.5081373,-0.0951836
+RB2,Millbank,51.4917605,-0.1298473
+RB4,Hilton Pier,51.4309209,-0.0936496
+RB4,Canary Wharf,51.5054306,-0.0235333
+RB5,Woolwich Arsenal,51.4894752,0.06758829999999999
+RB5,North Greenwich,51.4859576,0.007494900000000001
+RB6,Putney,51.4596431,-0.2141257
+RB6,Plantation Wharf,51.46679899999999,-0.1810273
+RB6,Blackfriars,51.51199200000001,-0.1038617
+RB6,Blackfriars,51.51199200000001,-0.1038617
+RB6,Bankside,51.5081373,-0.0951836
+RB6,Canary Wharf,51.5054306,-0.0235333
+RB6A,Canary Wharf,51.5054306,-0.0235333
+RB6A,Putney,51.4596431,-0.2141257
+RT1,Westminster Pier,51.4974948,-0.1356583
+RT1,Tower Pier,51.5073034,-0.07875549999999999
+RT1,Greenwich Pier,51.4933675,0.0098214
+RT3,Westminster Pier,51.4974948,-0.1356583
+RT3,St. Katherine's Pier,51.5064168,-0.0718167
+RT3,Greenwich Pier,51.4933675,0.0098214
+RT5,Bankside Pier,51.5085251,-0.0962555
+RT7,Embankment,51.4309209,-0.0936496
+RT7,North Greenwich,51.4859576,0.007494900000000001
+RT7,Woolwich Arsenal,51.4894752,0.06758829999999999
+RT8,St George Wharf,51.4848424,-0.1274566
+RT8,Bankside,51.5081373,-0.0951836
+RT10,Woolwich Arsenal,51.4894752,0.06758829999999999
+RT10,North Greenwich,51.4859576,0.007494900000000001
+RT11,Putney,51.4596431,-0.2141257
+RT11,Plantation Wharf,51.46679899999999,-0.1810273
+RT11,Blackfriars,51.51199200000001,-0.1038617
+RT11,Bankside,51.5081373,-0.0951836
+RT11,Canary Wharf,51.5054306,-0.0235333
+RT12,Canary Wharf,51.5054306,-0.0235333
+RT12,Putney,51.4596431,-0.2141257
+RV1,Covent Garden,51.5116571,-0.1240436
+RV1,Waterloo,51.5048541,-0.1136621
+RV1,London Bridge,51.5072178,-0.1275862
+RV1,City Hall,51.4309209,-0.0936496
+RV1,Tower Gateway,51.5106312,-0.0737553
+S1,Banstead,51.3221909,-0.205046
+S1,Belmont,51.601249,-0.3192749
+S1,Sutton Station,51.3614279,-0.193961
+S1,Sutton Town Centre,51.3614279,-0.193961
+S1,St Helier Hospital,51.3805311,-0.18442
+S1,Middleton Circle,51.4309209,-0.0936496
+S1,Lavender Fields,51.4309209,-0.0936496
+S3,Sutton Hospital,51.3614279,-0.193961
+S3,Sutton Station,51.3614279,-0.193961
+S3,Sutton Town Centre,51.3614279,-0.193961
+S3,"North Cheam, Sainsbury's",51.3723635,-0.2259143
+S3,Worchester Park,51.38029,-0.24468
+S3,Malden Manor,51.40066299999999,-0.259263
+S4,Roundshaw,51.3533066,-0.1269329
+S4,Wallington,51.363978,-0.151845
+S4,Belmont,51.601249,-0.3192749
+S4,Sutton Station,51.3614279,-0.193961
+S4,Sutton Town Centre,51.3614279,-0.193961
+S4,St Helier Station,51.3899,-0.19875
+U1,Ruislip,51.5758719,-0.421236
+U1,Uxbridge,51.5485,-0.479611
+U1,Hillingdon Hospital,51.5252078,-0.4612385
+U1,West Drayton,51.502985,-0.4654099999999999
+U2,Brunel University,51.5321389,-0.4727493
+U2,Hillingdon Station,51.5537882,-0.4499684
+U2,"Uxbridge, Lees Road",51.5285284,-0.4494669
+U2,Uxbridge,51.5485,-0.479611
+U3,Uxbridge,51.5485,-0.479611
+U3,Hillingdon Hospital,51.5252078,-0.4612385
+U3,West Drayton,51.502985,-0.4654099999999999
+U3,West Drayton,51.502985,-0.4654099999999999
+U3,Harmondsworth,51.487453,-0.475554
+U3,Heathrow Central,51.4724711,-0.4544586
+U4,"Hayes, Prologis Park",51.516758,-0.436786
+U4,"Hayes, Bourne Avenue",51.5026304,-0.438024
+U4,"Hayes, Station Road",51.501625,-0.4236355
+U4,"Hayes, Barra Hall Circus",51.516758,-0.436786
+U4,Hayes & Harlington Station,51.5029848,-0.4203779
+U4,"Hayes, Asda",51.516758,-0.436786
+U4,"Hayes, Barra Hall Circus",51.516758,-0.436786
+U4,"Hillingdon, Kingston Lane",51.532082,-0.4665415
+U4,Uxbridge,51.5485,-0.479611
+U5,Uxbridge,51.5485,-0.479611
+U5,Hillingdon Hospital,51.5252078,-0.4612385
+U5,West Drayton,51.502985,-0.4654099999999999
+U5,West Drayton,51.502985,-0.4654099999999999
+U5,Stockley Estate,51.5053199,-0.4501722
+U5,Stockley Park,51.51153850000001,-0.444799
+U5,Hayes & Harlington Station,51.5029848,-0.4203779
+U7,Uxbridge,51.5485,-0.479611
+U7,"Hillingdon, Kingston Lane",51.532082,-0.4665415
+U7,"Hillingdon, Pield Heath Road",51.5266189,-0.4608675
+U7,Charville Lane Estate,51.5378301,-0.4293177
+U7,"Hayes, Sainsbury's",51.516758,-0.436786
+U9,Uxbridge,51.5485,-0.479611
+U9,Harefield Hospital,51.6067699,-0.4827023999999999
+U10,Uxbridge,51.5485,-0.479611
+U10,Ickenham High Road,51.5670568,-0.4417871
+U10,Ruislip,51.5758719,-0.421236
+U10,"Ruislip, Heathfield Rise",51.5764892,-0.4378024
+UL1,Hammersmith,51.491187,-0.223731
+UL1,Baker Street,51.520568,-0.1567804
+UL2,Camden Road,51.5479475,-0.1303297
+UL2,Hampstead Heath,51.5608294,-0.1629416
+UL2,Willesden Junction,51.53211630000001,-0.2433689
+UL2,Willesden Junction,51.53211630000001,-0.2433689
+UL2,Willesden Junction,51.53211630000001,-0.2433689
+UL2,Gunnersbury,51.49335199999999,-0.278887
+UL2,Richmond,51.46131099999999,-0.303742
+UL3,Clapham Junction,51.4651737,-0.1708113
+UL3,Canada Water,51.4962989,-0.0482742
+UL4,High Barnet,51.6569225,-0.1949252
+UL4,Finchley Central,51.5971434,-0.1979547
+UL4,Archway,51.5648883,-0.1323808
+UL5,Acton,51.50837199999999,-0.27444
+UL5,Rayners Lane Station,51.5762173,-0.3702536
+UL6,Baker Street Station,51.5231548,-0.156863
+UL6,Willesden Green,51.5476301,-0.2369246
+UL6,Wembley Park,51.5585935,-0.2796126
+UL7,Barking,51.536563,0.075766
+UL7,East Ham,51.5333972,0.04991139999999999
+UL7,Walthamstow Central,51.5901769,-0.0173437
+UL8,Seven Sisters,51.582652,-0.0747232
+UL8,Seven Sisters,51.582652,-0.0747232
+UL8,Gospel Oak,51.5563205,-0.1492765
+UL9,Hammersmith,51.491187,-0.223731
+UL9,Turnham Green,51.49203019999999,-0.2663174
+UL9,Richmond,51.46131099999999,-0.303742
+UL10,Chingford Station,51.6320667,0.007362700000000001
+UL10,Hackney Downs,51.5553095,-0.06908249999999999
+UL10,Liverpool Street,51.5175001,-0.0826966
+UL11,Canary Wharf,51.5054306,-0.0235333
+UL11,Stratford,51.5426313,-0.0010369
+UL12,Loughton,51.655942,0.068161
+UL12,Snaresbrook,51.58567859999999,0.0084531
+UL12,Leyton,51.5702225,-0.0146938
+UL12,Stratford,51.5426313,-0.0010369
+UL12,Mile End,51.52354529999999,-0.0330122
+UL13,Harrow & Wealdstone Station,51.59172359999999,-0.3343587
+UL13,Watford Junction,51.66371280000001,-0.3964488
+UL14,Harrow-on-the-Hill,51.5706321,-0.3396363
+UL14,Wembley Park,51.5585935,-0.2796126
+UL15,Stanmore Station,51.617676,-0.311451
+UL15,Wembley Park,51.5585935,-0.2796126
+UL15,Stonebridge Park,51.5445824,-0.2608244
+UL16,Stratford,51.5426313,-0.0010369
+UL16,Ilford,51.556619,0.076251
+UL16,Romford,51.577076,0.178319
+UL17,Stanmore Station,51.617676,-0.311451
+UL17,Wembley Park,51.5585935,-0.2796126
+UL17,Willesden Green,51.5476301,-0.2369246
+UL18,Liverpool Street,51.5175001,-0.0826966
+UL18,Seven Sisters,51.582652,-0.0747232
+UL18,Enfield Town,51.6522994,-0.0807119
+UL18,Cheshunt,51.70264050000001,-0.0343787
+UL19,Harrow & Wealdstone Station,51.59172359999999,-0.3343587
+UL19,Wembley Central,51.550501,-0.3048409
+UL19,Stonebridge Park,51.5445824,-0.2608244
+UL19,Queen's Park,51.5345448,-0.2043853
+UL20,Tower Hill,51.5095757,-0.0760083
+UL20,Canning Town,51.5189494,0.0132
+UL20,Stratford,51.5426313,-0.0010369
+UL20,Stratford,51.5426313,-0.0010369
+UL20,East Ham,51.5333972,0.04991139999999999
+UL20,Barking,51.536563,0.075766
+UL21,Stratford,51.5426313,-0.0010369
+UL21,Hackney Central,51.5482344,-0.05738749999999999
+UL21,Camden Road,51.5479475,-0.1303297
+UL22,Stratford,51.5426313,-0.0010369
+UL22,Hampstead Heath,51.5608294,-0.1629416
+UL23,Dalston Kingsland,51.5481846,-0.05471409999999999
+UL23,Shadwell,51.51450620000001,-0.05711619999999999
+UL24,Dagenham East,51.5402631,0.1482103
+UL24,Barking,51.536563,0.075766
+UL25,Upminster,51.55591399999999,0.248894
+UL25,Barking,51.536563,0.075766
+UL26,Wimbledon,51.41833889999999,-0.2206288
+UL26,Wimbledon,51.41833889999999,-0.2206288
+UL26,Fulham Broadway,51.4801568,-0.1962971
+UL29,Osterley,51.4819722,-0.3494553
+UL29,Hammersmith,51.491187,-0.223731
+UL27,Finchley Central,51.5971434,-0.1979547
+UL27,Mill Hill East,51.6078622,-0.2082474
+UL28,Boston Manor,51.495767,-0.3247429000000001
+UL28,Hammersmith,51.491187,-0.223731
+UL30,South Wimbledon,51.41570919999999,-0.192514
+UL30,Fulham Broadway,51.4801568,-0.1962971
+UL31,All Saints,51.4309209,-0.0936496
+UL31,Bank,51.4309209,-0.0936496
+UL32,Arnos Grove,51.619799,-0.1296871
+UL32,High Barnet,51.6569225,-0.1949252
+UL33,Warren Street,51.5240516,-0.1399547
+UL33,Finchley Road,51.5611866,-0.197096
+UL34,Finchley Central,51.5971434,-0.1979547
+UL34,Arnos Grove,51.619799,-0.1296871
+UL34,Arnos Grove,51.619799,-0.1296871
+UL35,Finsbury Park,51.56457839999999,-0.1047257
+UL35,Walthamstow Central,51.5901769,-0.0173437
+UL35,Walthamstow Central,51.5901769,-0.0173437
+UL37,Victoria,51.49554149999999,-0.1435602
+UL37,Brixton,51.4612794,-0.1156148
+UL40,Chingford,51.6320667,0.007362700000000001
+UL40,Hackney Downs,51.5553095,-0.06908249999999999
+UL41,Morden,51.394943,-0.19446
+UL41,Tooting Broadway,51.427867,-0.1678142
+UL42,Stratford,51.5426313,-0.0010369
+UL42,Highbury & Islington,51.5569649,-0.0979656
+UL42,Camden Road,51.5479475,-0.1303297
+UL43,Wimbledon,51.41833889999999,-0.2206288
+UL43,Hammersmith,51.491187,-0.223731
+UL44,Stratford,51.5426313,-0.0010369
+UL44,Highbury & Islington,51.5569649,-0.0979656
+UL55,Chalk Farm,51.5444834,-0.152158
+UL55,Canons Park,51.6076736,-0.2962361
+UL56,Chalk Farm,51.5444834,-0.152158
+UL56,Hendon Central,51.583202,-0.226399
+W3,Northumberland Park,51.6024517,-0.0676958
+W3,White Hart Lane Station,51.6061468,-0.0884635
+W3,"White Hart Lane, Fenton Road",51.6067192,-0.0913817
+W3,Wood Green,51.5971722,-0.1098021
+W3,"Alexandra Park, Park Road",51.4309209,-0.0936496
+W3,Crouch End,51.5819979,-0.1221464
+W3,Finsbury Park Station,51.5646425,-0.1058553
+W4,Oakthorpe Park,51.4309209,-0.0936496
+W4,"Wood Green, Wolves Lane",51.6058398,-0.1036382
+W4,Wood Green,51.5971722,-0.1098021
+W4,Wood Green,51.5971722,-0.1098021
+W4,Turnpike Lane Station,51.5904278,-0.1027587
+W4,"Green Lanes, West Green Road",51.5889244,-0.1020963
+W4,Tottenham Town Hall,51.5872187,-0.0725467
+W4,Bruce Grove,51.596249,-0.0723585
+W4,Bruce Grove,51.596249,-0.0723585
+W4,Tottenham Hale,51.5892808,-0.06105049999999999
+W4,"Tottenham Hale, Ferry Lane",51.5880499,-0.0605514
+W5,Archway,51.5648883,-0.1323808
+W5,Crouch End,51.5819979,-0.1221464
+W5,Crouch End,51.5819979,-0.1221464
+W5,Harringay Station,51.5773498,-0.1050857
+W5,"Harringay, Superstores",51.582426,-0.09966
+W6,Southgate,51.4911405,-0.2261411
+W6,"Palmers Green, Hedge Lane",51.6224407,-0.0997349
+W6,"Edmonton, Cambridge",51.4309209,-0.0936496
+W6,Edmonton Green,51.6248126,-0.0581806
+W7,Muswell Hill,51.5911816,-0.1443015
+W7,"Alexandra Park, Park Road",51.4309209,-0.0936496
+W7,Crouch End,51.5819979,-0.1221464
+W7,Finsbury Park Station,51.5646425,-0.1058553
+W8,Chase Farm Hospital,51.66689239999999,-0.1028125
+W8,Enfield,51.6522994,-0.0807119
+W8,Edmonton Green,51.6248126,-0.0581806
+W8,Lee Valley Leisure Complex,51.6318241,-0.0376722
+W9,Chase Farm Hospital,51.66689239999999,-0.1028125
+W9,Enfield,51.6522994,-0.0807119
+W9,Highlands Village,51.6464013,-0.1111452
+W9,Southgate,51.5280043,-0.18519
+W10,Crews Hill,51.6843047,-0.1105717
+W10,"Enfield Town, Cecil Road",51.6507162,-0.0802953
+W11,Chingford Hall Estate,51.609421,-0.025236
+W11,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+W11,Walthamstow Central,51.5830128,-0.019886
+W12,"Walthamstow, Coppermill Lane",51.5803038,-0.0403725
+W12,Walthamstow Central,51.5830128,-0.019886
+W12,St James Street,51.5064993,-0.1393328
+W12,Whipps Cross,51.5095281,-0.229236
+W12,South Woodford,51.5095281,-0.229236
+W12,Wanstead,51.5767971,0.0249881
+W13,Leytonstone,51.51719869999999,-0.3207339
+W13,Wanstead,51.5767971,0.0249881
+W13,South Woodford,51.5912671,0.0264721
+W13,Woodford Green,51.6092549,0.0405521
+W13,Woodford Wells,51.51719869999999,-0.3207339
+W14,Woodford Bridge,51.6057309,0.0544589
+W14,Charlie Brown's Roundabout,51.5934938,0.0370989
+W14,South Woodford,51.4964278,-0.2085211
+W14,Wanstead,51.4964278,-0.2085211
+W14,Green Man Roundabout,51.5705591,0.0145584
+W14,Leytonstone,51.4964278,-0.2085211
+W14,"Leytonstone, Harrow Green",51.5582955,0.007356
+W14,Leyton,51.4964278,-0.2085211
+W14,"Leyton, Superstores",51.5558965,-0.0093311
+W15,"Higham Hill, Cogan Avenue",51.6012336,-0.0363719
+W15,"Forest Road, Palmerston Road",51.5858953,-0.0292291
+W15,Walthamstow Central,51.5830128,-0.019886
+W15,"Leyton, Bakers Arms",51.5749185,-0.013549
+W15,Whipps Cross,51.581499,0.0001219
+W15,Leytonstone,51.5649624,0.0088141
+W15,"Leyton, Town Hall",51.5702225,-0.0146938
+W15,Spitalfields Market,51.5197441,-0.07606879999999999
+W15,Spitalfields Market,51.5197441,-0.07606879999999999
+W15,Homerton Hospital,51.5478609,-0.0425903
+W15,Hackney Town Hall,51.54507210000001,-0.0563459
+W16,Chingford Mount,51.6185735,-0.0180318
+W16,Chingford Hatch,51.420389,-0.1287668
+W16,Highams Park,51.6083754,0.0014712
+W16,"Walthamstow, Wood Street",51.5864747,-0.0026968
+W16,"Leyton, Bakers Arms",51.5749185,-0.013549
+W16,Leytonstone,51.5649624,0.0088141
+W19,"Walthamstow, Argall Avenue",51.5701165,-0.0387872
+W19,St James Street,51.5064993,-0.1393328
+W19,Walthamstow Central,51.5830128,-0.019886
+W19,Whipps Cross,51.4255297,-0.2050566
+W19,Leytonstone,51.5649624,0.0088141
+W19,"Wanstead, Centre Road",51.5596482,0.0253062
+W19,Manor Park,51.550487,0.0514117
+W19,Ilford Broadway,51.4191743,-0.2000351
+W19,Ilford,51.4255297,-0.2050566
+X26,Heathrow Central,51.471184,-0.4527179999999999
+X26,Hatton Cross,51.4651031,-0.4157165
+X26,Kingston,51.41233,-0.300689
+X26,Sutton Town Centre,51.3614279,-0.193961
+X26,Wallington Green,51.3669885,-0.1543945
+X26,West Croydon,51.3769529,-0.0956895
+X68,"West Croydon, Limited Stop",51.3769529,-0.0956895
+X68,"Russell Square, Limited Stop",51.4309209,-0.0936496
+N1,Tottenham Court Road,51.5203145,-0.1340121
+N1,Aldwych,51.5132441,-0.1172819
+N1,Waterloo,51.5048541,-0.1136621
+N1,Elephant & Castle,51.4938058,-0.0977932
+N1,Bricklayer's Arms,51.4661409,-0.2174147
+N1,Surrey Quays,51.4944172,-0.0383063
+N1,"Greenwich, Cutty Sark",51.4933675,0.0098214
+N1,Charlton,51.4900403,0.0307737
+N1,Woolwich,51.4894752,0.06758829999999999
+N1,Plumstead Station,51.4896774,0.0847463
+N1,Abbey Wood,51.4926116,0.1188182
+N1,Thamesmead,51.50575809999999,0.1100586
+N2,Crystal Palace,51.4197233,-0.0830638
+N2,West Norwood,51.427905,-0.1002486
+N2,Tulse Hill Station,51.43986,-0.10505
+N2,"Brixton, Morval Road",51.456008,-0.1128301
+N2,Brixton,51.4612794,-0.1156148
+N2,Stockwell,51.4760412,-0.1263271
+N2,Vauxhall,51.4861671,-0.12172
+N2,Victoria,51.49554149999999,-0.1435602
+N2,Hyde Park Corner,51.5029347,-0.1508562
+N2,Marble Arch,51.5132225,-0.1588937
+N2,Marylebone,51.5188746,-0.1498955
+N3,Oxford Circus,51.5152543,-0.1420395
+N3,Piccadilly Circus,51.5099734,-0.13497
+N3,"Whitehall, Horse Guards",51.5049889,-0.1265748
+N3,Parliament Square,51.5010421,-0.1268514
+N3,Kennington Lane,51.4884765,-0.1112969
+N3,Kennington Church,51.5055111,-0.1940999
+N3,Brixton,51.4612794,-0.1156148
+N3,Brixton,51.4612794,-0.1156148
+N3,"Brixton, Morval Road",51.456008,-0.1128301
+N3,Herne Hill,51.4609208,-0.0985404
+N3,South Croxted Road,51.432326,-0.0894342
+N3,Crystal Palace,51.4197233,-0.0830638
+N3,Penge,51.41388490000001,-0.0570112
+N3,Beckenham Junction,51.40817,-0.025813
+N3,Bromley North,51.406025,0.013156
+N5,Edgware,51.61548819999999,-0.2609598
+N5,Colindale,51.5896908,-0.2491029
+N5,Burnt Oak Broadway,51.602753,-0.2700278
+N5,Hendon Central,51.583202,-0.226399
+N5,Golders Green,51.5740013,-0.1987725
+N5,Camden Town,51.5390261,-0.1425516
+N5,Camden Town,51.5390261,-0.1425516
+N5,Mornington Crescent,51.5334445,-0.1404782
+N5,Warren Street,51.5240516,-0.1399547
+N5,Tottenham Court Road,51.5203145,-0.1340121
+N5,Trafalgar Square,51.508039,-0.128069
+N7,Northolt,51.546615,-0.373103
+N7,Greenford Broadway,51.5279556,-0.3540139
+N7,Ealing Broadway,51.5132537,-0.3043136
+N7,"Acton, High Street",51.5071042,-0.270558
+N7,East Acton,51.5127758,-0.2476803
+N7,East Acton,51.5127758,-0.2476803
+N7,North Pole Road,51.5195492,-0.2265871
+N7,Ladbroke Grove,51.5178769,-0.2103321
+N7,Chepstow Road,51.5167339,-0.1955587
+N7,Chepstow Road,51.5167339,-0.1955587
+N7,Edgware Road Station,51.51988249999999,-0.1678336
+N7,Marble Arch,51.5132225,-0.1588937
+N7,Oxford Circus,51.5152543,-0.1420395
+N8,"Hainault, The Lowe",51.6099517,0.1092883
+N8,Barkingside,51.5833118,-0.1236257
+N8,Gants Hill,51.5767812,0.0661732
+N8,Redbridge Station,51.5763264,0.0453986
+N8,Wanstead,51.5833118,-0.1236257
+N8,Leytonstone,51.5833118,-0.1236257
+N8,Stratford,51.5833118,-0.1236257
+N8,Bow Interchange,51.52974,-0.0140839
+N8,Old Ford,51.535812,-0.021259
+N8,"Roman Road, Grove Road",51.531048,-0.03955699999999999
+N8,Shoreditch,51.5229106,-0.0777472
+N8,Liverpool Street,51.5175001,-0.0826966
+N8,St. Paul's,51.5833118,-0.1236257
+N8,City Thameslink,51.5140438,-0.1033475
+N8,Holborn,51.5833118,-0.1236257
+N8,Tottenham Court Road,51.5203145,-0.1340121
+N8,Oxford Circus,51.51521169999999,-0.1418553
+N9,Aldwych,51.5132441,-0.1172819
+N9,Trafalgar Square,51.508039,-0.128069
+N9,Green Park,51.62810440000001,-0.0559765
+N9,Hyde Park Corner,51.5029347,-0.1508562
+N9,Hyde Park Corner,51.5029347,-0.1508562
+N9,Royal Albert Hall,51.5009088,-0.177366
+N9,Hammersmith,51.62810440000001,-0.0559765
+N9,Turnham Green,51.49203019999999,-0.2663174
+N9,Chiswick Roundabout,51.4910362,-0.2816861
+N9,"Brentford, County Court",51.4842409,-0.3043609
+N9,"Hounslow, Bus Station",51.4708688,-0.3546457
+N9,Hounslow West,51.469435,-0.3837709
+N9,Heathrow Central,51.62810440000001,-0.0559765
+N9,Heathrow Terminal 5,51.471466,-0.4879806
+N11,Ealing Broadway,51.5146192,-0.3022912
+N11,Northfields,51.5041461,-0.3186474
+N11,"Acton, High Street",51.5071042,-0.270558
+N11,Hammersmith,51.6175062,-0.1385339
+N11,"Chelsea, World's End",51.6175062,-0.1385339
+N11,"Whitehall, Horse Guards",51.5049889,-0.1265748
+N11,Aldwych,51.5132441,-0.1172819
+N11,Ludgate Circus,51.5140306,-0.1043143
+N11,Liverpool Street,51.5175001,-0.0826966
+N15,Romford Market,51.5790739,0.1813886
+N15,Roneo Corner,51.5655709,0.1869165
+N15,Becontree Heath,51.5609465,0.1488995
+N15,Bennett's Castle Lane,51.5562949,0.1276031
+N15,Fair Cross,51.5833519,-0.07649299999999999
+N15,Barking,51.5833519,-0.07649299999999999
+N15,Barking,51.5833519,-0.07649299999999999
+N15,"East Ham, Newham Town Hall",51.53280239999999,0.0551608
+N15,Upton Park,51.53471750000001,0.0337596
+N15,"Canning Town, Barking Road",51.5180017,0.0130984
+N15,Canning Town,51.5189494,0.0132
+N15,"Poplar, All Saints",51.5105521,-0.0118612
+N15,"Limehouse, Burdett Road",51.5150014,-0.0285662
+N15,Aldgate,51.5134365,-0.0772463
+N15,Cannon Street,51.5119949,-0.091962
+N15,Ludgate Circus,51.5140306,-0.1043143
+N15,Aldwych,51.5132441,-0.1172819
+N15,Trafalgar Square,51.508039,-0.128069
+N16,Edgware,51.5623078,-0.0764353
+N16,Burnt Oak Broadway,51.602753,-0.2700278
+N16,Cricklewood Bus Garage,51.56195959999999,-0.2224221
+N16,Cricklewood Broadway,51.5567072,-0.2153734
+N16,Kilburn High Road Station,51.537243,-0.192318
+N16,Kilburn High Road Station,51.537243,-0.192318
+N16,Edgware Road Station,51.51988249999999,-0.1678336
+N16,Marble Arch,51.5132225,-0.1588937
+N16,"Park Lane, Hilton Hotel",51.5623078,-0.0764353
+N16,Victoria,51.49554149999999,-0.1435602
+N18,"Harrow Weald, Bus Garage",51.6064297,-0.3405434
+N18,Harrow,51.61493060000001,-0.0765796
+N18,Sudbury,51.5556591,-0.3171114
+N18,Craven Park,51.5409981,-0.2563872
+N18,"Harlesden, Jubilee Clock",51.5354215,-0.2479155
+N18,"Harrow Road, Police Station",51.552225,-0.3025793
+N18,"Harrow Road, Warwick Avenue",51.521152,-0.1806301
+N18,Paddington Green,51.5207075,-0.1737114
+N18,Baker Street Station,51.5231548,-0.156863
+N18,Oxford Circus,51.51521169999999,-0.1418553
+N18,Piccadilly Circus,51.5099734,-0.13497
+N18,Trafalgar Square,51.508039,-0.128069
+N19,Finsbury Park Station,51.5646425,-0.1058553
+N19,Highbury Barn,51.553813,-0.09808739999999999
+N19,Highbury & Islington,51.5648883,-0.1323808
+N19,Islington Green,51.5359664,-0.1028448
+N19,Rosebery Avenue,51.5262828,-0.1094047
+N19,Holborn,51.5648883,-0.1323808
+N19,Piccadilly Circus,51.5099734,-0.13497
+N19,Hyde Park Corner,51.5029347,-0.1508562
+N19,Hyde Park Corner,51.5029347,-0.1508562
+N19,Sloane Square,51.4927684,-0.1570174
+N19,Sloane Square,51.4927684,-0.1570174
+N19,"Battersea Bridge, South Side",51.4811674,-0.1725411
+N19,Clapham Junction,51.4651737,-0.1708113
+N20,Barnet Church,51.6526856,-0.1992227
+N20,Totteridge & Whetstone,51.630241,-0.179144
+N20,North Finchley,51.6135087,-0.1754198
+N20,East Finchley,51.592468,-0.1664342
+N20,East Finchley,51.592468,-0.1664342
+N20,Archway,51.63585519999999,-0.1947779
+N20,Camden Town,51.63585519999999,-0.1947779
+N20,Camden Town,51.63585519999999,-0.1947779
+N20,Mornington Crescent,51.5343501,-0.1388961
+N20,Euston,51.5280408,-0.1333271
+N20,Warren Street,51.63585519999999,-0.1947779
+N20,Trafalgar Square,51.508039,-0.128069
+N21,"Bexleyheath, Shopping Centre",51.6359737,-0.1002426
+N21,Blendon,51.6359737,-0.1002426
+N21,"Eltham, High Street",51.4507726,0.0561761
+N21,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+N21,New Cross,51.4769047,-0.0336897
+N21,New Cross Gate,51.4749904,-0.0403466
+N21,New Cross Gate,51.4749904,-0.0403466
+N21,Bricklayer's Arms,51.4661322,-0.2166946
+N21,London Bridge,51.6359737,-0.1002426
+N21,Ludgate Circus,51.5140306,-0.1043143
+N21,Aldwych,51.5132441,-0.1172819
+N21,Trafalgar Square,51.508039,-0.128069
+N22,Fulwell,51.6017398,-0.1148607
+N22,Richmond,51.6017398,-0.1148607
+N22,"North Sheen, Manor Circus",51.4653637,-0.2863842
+N22,Putney Bridge,51.4669712,-0.2129034
+N22,Parsons Green,51.4747689,-0.2002723
+N22,"Chelsea, World's End",51.6017398,-0.1148607
+N22,Sloane Square,51.4927684,-0.1570174
+N22,Knightsbridge,51.4991195,-0.1644394
+N22,Hyde Park Corner,51.5029347,-0.1508562
+N22,Green Park,51.6017398,-0.1148607
+N22,Piccadilly Circus,51.5099734,-0.13497
+N26,Trafalgar Square,51.508039,-0.128069
+N26,Ludgate Circus,51.5140306,-0.1043143
+N26,Liverpool Street,51.5175001,-0.0826966
+N26,Shoreditch,51.5229106,-0.0777472
+N26,Ash Grove,51.5358094,-0.0581907
+N26,"Hackney, Well Street",51.5424028,-0.0488388
+N26,Hackney Wick,51.544579,-0.0256935
+N26,Walthamstow Central,51.5901769,-0.0173437
+N26,"Walthamstow, Crooked Billet",51.601088,-0.0159737
+N26,Chingford Mount,51.6185735,-0.0180318
+N26,Chingford Station,51.6320667,0.007362700000000001
+N28,Camden Town,51.53328,-0.1734435
+N28,Chalk Farm,51.5444834,-0.152158
+N28,Swiss Cottage,51.53328,-0.1734435
+N28,Swiss Cottage,51.53328,-0.1734435
+N28,South Hampstead Stn,51.5412969,-0.1790611
+N28,Kilburn Park,51.53504119999999,-0.1938988
+N28,"Maida Hill, The Chippenham",51.5272288,-0.1769259
+N28,Westbourne Park,51.53328,-0.1734435
+N28,Notting Hill Gate,51.5092063,-0.1962355
+N28,"Kensington, Holland Road",51.5010095,-0.1932794
+N28,West Brompton,51.483494,-0.196802
+N28,Fulham Broadway,51.4803328,-0.1943638
+N28,"Wandsworth Bridge, South Side",51.4651939,-0.1880094
+N28,Wandsworth,51.53328,-0.1734435
+N29,Enfield,51.6522994,-0.0807119
+N29,Wood Green,51.5971722,-0.1098021
+N29,Turnpike Lane Station,51.5904278,-0.1027587
+N29,Finsbury Park Station,51.5646425,-0.1058553
+N29,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+N29,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+N29,Mornington Crescent,51.5334445,-0.1404782
+N29,Warren Street,51.5240516,-0.1399547
+N29,Trafalgar Square,51.508039,-0.128069
+N31,Camden Town,51.5390261,-0.1425516
+N31,Chalk Farm,51.5444834,-0.152158
+N31,Swiss Cottage,51.5425872,-0.1724737
+N31,South Hampstead Station,51.5412969,-0.1790611
+N31,Kilburn High Road Station,51.537243,-0.192318
+N31,Kilburn Park,51.53504119999999,-0.1938988
+N31,"Maida Hill, The Chippenham",51.5243627,-0.2017331
+N31,Notting Hill Gate,51.5090534,-0.1966727
+N31,Westbourne Park,51.51769299999999,-0.194941
+N31,"Kensington, Commonwealth Institute",51.5010095,-0.1932794
+N31,Earls Court Station,51.4915677,-0.1939564
+N31,Clapham Junction,51.4651737,-0.1708113
+N38,Walthamstow Central,51.5901769,-0.0173437
+N38,Clapton Pond,51.5561061,-0.05490830000000001
+N38,Mildmay Park,51.5488355,-0.0843157
+N38,Islington Angel,51.5346761,-0.1042905
+N38,Rosebery Avenue,51.5262828,-0.1094047
+N38,Piccadilly Circus,51.5099734,-0.13497
+N38,Hyde Park Corner,51.5029347,-0.1508562
+N38,Victoria,51.49554149999999,-0.1435602
+N41,Trafalgar Square,51.508039,-0.128069
+N41,Holborn,51.5175802,-0.1145147
+N41,Rosebery Avenue,51.5262828,-0.1094047
+N41,Islington Angel,51.5346761,-0.1042905
+N41,Islington Green,51.5359664,-0.1028448
+N41,Highbury & Islington,51.5569649,-0.0979656
+N41,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+N41,Archway,51.5648883,-0.1323808
+N41,Hornsey Rise,51.5721143,-0.12519
+N41,Hornsey,51.5872715,-0.1103806
+N41,West Green,51.586254,-0.0867628
+N41,Turnpike Lane Station,51.5904278,-0.1027587
+N41,Seven Sisters,51.582652,-0.0747232
+N41,Tottenham Hale,51.5892808,-0.06105049999999999
+N44,Aldwych,51.5132441,-0.1172819
+N44,Victoria,51.49554149999999,-0.1435602
+N44,Battersea Park Station,51.47220069999999,-0.165547
+N44,Wandsworth,51.45837299999999,-0.1891356
+N44,Tooting Station,51.41986989999999,-0.16136
+N44,Mitcham,51.402869,-0.166709
+N44,Sutton Station,51.3614279,-0.193961
+N55,Woodford Wells,51.6148287,0.0282889
+N55,South Woodford,51.5912671,0.0264721
+N55,Wanstead,51.5767971,0.0249881
+N55,Whipps Cross,51.581499,0.0001219
+N55,"Leyton, Bakers Arms",51.5749185,-0.013549
+N55,Clapton Pond,51.5561061,-0.05490830000000001
+N55,Hackney Well Street,51.5424028,-0.0488388
+N55,Ash Grove,51.5358094,-0.0581907
+N55,Shoreditch,51.5229106,-0.0777472
+N55,Old Street Station,51.5256719,-0.0874922
+N55,Old Street Station,51.5256719,-0.0874922
+N55,Clerkenwell Green,51.522739,-0.1060289
+N55,Holborn,51.5175802,-0.1145147
+N55,Holborn,51.5175802,-0.1145147
+N55,Oxford Circus,51.5152543,-0.1420395
+N55,"Leyton, Bakers Arms",51.5749185,-0.013549
+N63,Crystal Palace,51.4197233,-0.0830638
+N63,Honor Oak,51.4489977,-0.0457341
+N63,Peckham Rye,51.4603208,-0.0603961
+N63,Peckham,51.47032369999999,-0.0673872
+N63,Elephant & Castle,51.4938058,-0.0977932
+N63,Clerkenwell Green,51.522739,-0.1060289
+N63,King's Cross,51.5347488,-0.1245845
+N68,Old Coulsdon,51.298482,-0.114175
+N68,Coulsdon,51.319941,-0.141267
+N68,Purley,51.339228,-0.119711
+N68,"South Croydon, South End",51.3650199,-0.099012
+N68,Croydon Town Centre,51.3769529,-0.0956895
+N68,Upper Norwood,51.41376716037048, -0.09204081941649297
+N68,Upper Norwood,51.41376716037048, -0.09204081941649297
+N68,Tulse Hill Station,51.43986,-0.10505
+N68,Herne Hill,51.4609208,-0.0985404
+N68,Camberwell Green,51.4748827,-0.0921158
+N68,Elephant & Castle,51.4938058,-0.0977932
+N68,Waterloo,51.5048541,-0.1136621
+N68,Aldwych,51.5132441,-0.1172819
+N68,Tottenham Court Road,51.5203145,-0.1340121
+N73,Victoria,51.49554149999999,-0.1435602
+N73,"Park Lane, Hilton Hotel",51.5083331,-0.1547189
+N73,Marble Arch,51.5132225,-0.1588937
+N73,Oxford Circus,51.5152543,-0.1420395
+N73,Euston,51.5280408,-0.1333271
+N73,King's Cross,51.5347488,-0.1245845
+N73,Islington Angel,51.5346761,-0.1042905
+N73,Newington Green,51.5514507,-0.0857535
+N73,Stoke Newington,51.561175,-0.08349229999999999
+N73,Stamford Hill,51.5696514,-0.0750199
+N73,"Tottenham, Town Hall",51.5872187,-0.0725467
+N73,Tottenham Hale,51.5892808,-0.06105049999999999
+N73,Walthamstow Central,51.5901769,-0.0173437
+N74,"Roehampton, Danebury Avenue",51.451943,-0.247966
+N74,Putney Bridge,51.4669712,-0.2129034
+N74,West Brompton,51.483494,-0.196802
+N74,Earl's Court,51.490331,-0.1958417
+N74,Hyde Park Corner,51.5029347,-0.1508562
+N74,Marble Arch,51.5132225,-0.1588937
+N74,Portman Square,51.5161534,-0.1560125
+N74,Baker Street Station,51.5231548,-0.156863
+N83,Golders Green,51.5740013,-0.1987725
+N83,"Hendon, Queens Road",51.5833703,-0.222686
+N83,West Hendon Broadway,51.5772325,-0.2392682
+N83,Kingsbury Green,51.5814409,-0.2619577
+N83,Wembley Arena,51.550501,-0.3048409
+N83,Wembley Stadium,51.55602469999999,-0.2796177
+N83,Alperton,51.539601,-0.2988365
+N83,"Alperton, Sainsbury's",51.5383862,-0.3028583
+N83,Ealing Broadway,51.5132537,-0.3043136
+N83,Ealing Broadway,51.5132537,-0.3043136
+N83,Ealing Hospital,51.5075205,-0.3465216
+N86,Stratford,51.5426313,-0.0010369
+N86,"Woodgrange Park, Katherine Road",51.5391367,0.0407963
+N86,Manor Park,51.550487,0.0514117
+N86,Ilford Broadway,51.5584078,0.07077839999999999
+N86,Ilford,51.556619,0.076251
+N86,Chadwell Heath,51.5722283,0.141995
+N86,Romford North Street Bus Garage,51.5823836,0.1761951
+N86,Romford Market,51.577076,0.178319
+N86,Romford Station,51.57472449999999,0.1826519
+N86,"Gallows Corner, Main Road",51.5922565,0.2142701
+N86,Gallows Corner,51.59188200000001,0.214546
+N86,"Harold Hill, Dagnam Park Square",51.6049149,0.2445527
+N87,Kingston,51.41233,-0.300689
+N87,"New Malden, Fountain Roundabout",51.40066299999999,-0.259263
+N87,Raynes Park,51.4084257,-0.2298751
+N87,Wimbledon,51.41833889999999,-0.2206288
+N87,Wandsworth,51.45837299999999,-0.1891356
+N87,Clapham Junction,51.4651737,-0.1708113
+N87,Clapham Junction,51.4651737,-0.1708113
+N87,Vauxhall,51.4861671,-0.12172
+N87,"Whitehall, Horse Guards",51.5049889,-0.1265748
+N87,Aldwych,51.5132441,-0.1172819
+N89,Trafalgar Square,51.508039,-0.128069
+N89,New Cross Gate,51.4749904,-0.0403466
+N89,Blackheath Village,51.4657729,0.0091238
+N89,"Blackheath, Royal Standard",51.4658393,0.0090338
+N89,"Shooters Hill Road, Sun-In-The-Sands",51.4745909,0.0240901
+N89,"Shooters Hill, Eaglesfield Road",51.4686795,0.06966449999999999
+N89,Welling Corner,51.4626258,0.1081541
+N89,"Bexleyheath, Shopping Centre",51.45334099999999,0.13822
+N89,"Bexleyheath, Bus Garage",51.46006930000001,0.1534245
+N89,"Northend Road, Thames Road",51.4686147,0.1810608
+N89,Slade Green,51.4695282,0.1928854
+N89,Erith,51.480818,0.174675
+N91,Cockfosters,51.647851,-0.151255
+N91,Oakwood,51.6481224,-0.1309298
+N91,Southgate,51.62476119999999,-0.1240456
+N91,Arnos Grove,51.619799,-0.1296871
+N91,Wood Green Station,51.5971722,-0.1098021
+N91,Turnpike Lane Station,51.5904278,-0.1027587
+N91,Crouch End,51.5819979,-0.1221464
+N91,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+N91,King's Cross,51.5347488,-0.1245845
+N91,Russell Square,51.5221667,-0.1249807
+N91,Aldwych,51.5132441,-0.1172819
+N91,Trafalgar Square,51.508039,-0.128069
+N97,Hammersmith,51.491187,-0.223731
+N97,Earl's Court,51.490331,-0.1958417
+N97,Hyde Park Corner,51.5029347,-0.1508562
+N97,Hyde Park Corner,51.5029347,-0.1508562
+N97,Green Park,51.5039052,-0.1438484
+N97,Piccadilly Circus,51.5099734,-0.13497
+N97,Trafalgar Square,51.508039,-0.128069
+N98,Stanmore Station,51.617676,-0.311451
+N98,Queensbury Station,51.5942415,-0.2861271
+N98,Kingsbury Circle,51.5853429,-0.2812115
+N98,"Neasden, Shopping Centre",51.5626819,-0.2536987
+N98,"Willesden, Bus Garage",51.5474482,-0.2394372
+N98,/,51.4309209,-0.0936496
+N98,Kilburn Park,51.53504119999999,-0.1938988
+N98,Marble Arch,51.5132225,-0.1588937
+N98,Marble Arch,51.5132225,-0.1588937
+N98,Oxford Circus,51.5152543,-0.1420395
+N98,Holborn,51.5175802,-0.1145147
+N109,Croydon Town Centre,51.3769529,-0.0956895
+N109,West Croydon,51.3769529,-0.0956895
+N109,Thornton Heath Pond,51.3941232,-0.1146955
+N109,"Streatham, Green Lane",51.4147104,-0.1158693
+N109,Streatham Station,51.4259857,-0.131308
+N109,Streatham Hill Station,51.4382009,-0.1270706
+N109,Kennington Church,51.5055111,-0.1940999
+N109,Kennington Lane,51.4884765,-0.1112969
+N109,Trafalgar Square,51.508039,-0.128069
+N109,Oxford Circus,51.5152543,-0.1420395
+N113,Edgware,51.61548819999999,-0.2609598
+N113,Apex Corner,51.4369075,-0.3784005
+N113,Hendon Central,51.583202,-0.226399
+N113,Hendon Central,51.583202,-0.226399
+N113,Swiss Cottage,51.5425872,-0.1724737
+N113,Baker Street Station,51.5231548,-0.156863
+N113,Trafalgar Square,51.508039,-0.128069
+N133,Morden,51.394943,-0.19446
+N133,Mitcham,51.402869,-0.166709
+N133,"Rowan Road, Manor Road",51.4039785,-0.136848
+N133,"Streatham, St. Leonard's Church",51.42926610000001,-0.1311095
+N133,Streatham Hill Station,51.4382009,-0.1270706
+N133,Brixton,51.4612794,-0.1156148
+N133,Kennington Church,51.5055111,-0.1940999
+N133,Elephant & Castle,51.4938058,-0.0977932
+N133,London Bridge,51.5078788,-0.0877321
+N133,Monument,51.4309209,-0.0936496
+N133,Liverpool Street,51.5175001,-0.0826966
+N136,Oxford Circus,51.5152543,-0.1420395
+N136,Piccadilly Circus,51.5099734,-0.13497
+N136,"Whitehall, Horse Guards",51.5049111,-0.1273704
+N136,Vauxhall,51.4861671,-0.12172
+N136,Camberwell Green,51.4748827,-0.0921158
+N136,Peckham,51.47032369999999,-0.0673872
+N136,New Cross Gate,51.4749904,-0.0403466
+N136,New Cross,51.4769047,-0.0336897
+N136,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+N136,"Catford, Town Centre",51.4453954,-0.0160913
+N136,"Downham, Bromley Road",51.4249009,-0.0042485
+N136,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+N136,Grove Park,51.4329249,0.021203
+N136,"Chislehurst, War Memorial",51.4124839,0.07390759999999999
+N137,Crystal Palace,51.4197233,-0.0830638
+N137,"Norwood, Crown Point",41.4169806,-87.3653135
+N137,Streatham Hill Station,51.4382009,-0.1270706
+N137,"Streatham Hill, Telford Avenue",51.4421746,-0.1300019
+N137,Clapham Common,51.4556465,-0.1385544
+N137,Clapham Park,51.4476066,-0.1431943
+N137,Queenstown Road Station,51.4749596,-0.1466578
+N137,Battersea Park Station,51.47696,-0.14751
+N137,Sloane Square,51.4927684,-0.1570174
+N137,Sloane Square,51.4927684,-0.1570174
+N137,Hyde Park Corner,51.5029347,-0.1508562
+N137,Marble Arch,51.5132225,-0.1588937
+N137,Oxford Circus,51.5152543,-0.1420395
+N155,Morden,51.394943,-0.19446
+N155,Tooting Broadway,51.427867,-0.1678142
+N155,Clapham Common,51.4556465,-0.1385544
+N155,Stockwell,51.4760412,-0.1263271
+N155,Elephant & Castle,51.4938058,-0.0977932
+N155,"Whitehall, Horse Guards",51.5049111,-0.1273704
+N155,Aldwych,51.5132441,-0.1172819
+N171,Hither Green Station,51.4519061,-0.0007435
+N171,"Catford, Town Centre",51.4453954,-0.0160913
+N171,Brockley Rise,51.4473951,-0.0416563
+N171,New Cross Gate,51.4749904,-0.0403466
+N171,Peckham,51.47032369999999,-0.0673872
+N171,Camberwell Green,51.4748827,-0.0921158
+N171,Elephant & Castle,51.4938058,-0.0977932
+N171,Waterloo,51.5048541,-0.1136621
+N171,Aldwych,51.5132441,-0.1172819
+N171,Tottenham Court Road,51.5203145,-0.1340121
+N199,Trafalgar Square,51.508039,-0.128069
+N199,Aldwych,51.5132441,-0.1172819
+N199,London Bridge,51.5078788,-0.0877321
+N199,Canada Water,51.4962989,-0.0482742
+N199,Surrey Quays,51.4944172,-0.0383063
+N199,Deptford,51.4807988,-0.0231099
+N199,"Greenwich, Cutty Sark",51.4828646,-0.0095917
+N199,Lewisham,51.46115090000001,-0.0073177
+N199,"Lewisham, Shopping Centre",51.46175909999999,-0.0119106
+N199,"Bellingham, Catford Bus Garage",51.434704,-0.017839
+N199,Bromley South,51.406025,0.013156
+N199,Petts Wood,51.389636,0.08195
+N199,"Orpington, Perry Hall Road",51.3823992,0.0998353
+N199,St. Mary Cray Station,51.3957762,0.1071945
+N205,Paddington,51.515973,-0.174943
+N205,Marylebone,51.5188746,-0.1498955
+N205,Baker Street Station,51.5231548,-0.156863
+N205,Warren Street,51.5240516,-0.1399547
+N205,Warren Street,51.5240516,-0.1399547
+N205,Euston,51.5280408,-0.1333271
+N205,King's Cross,51.5347488,-0.1245845
+N205,Islington Angel,51.5346761,-0.1042905
+N205,Old Street Station,51.5256719,-0.0874922
+N205,Liverpool Street,51.5175001,-0.0826966
+N205,Aldgate,51.5134365,-0.0772463
+N205,Whitechapel,51.5148198,-0.0650534
+N205,Mile End,51.52354529999999,-0.0330122
+N205,Bow Church,51.5287753,-0.0167013
+N205,Leyton Downsell Road,51.5533905,-0.0020391
+N207,Uxbridge,51.5485,-0.479611
+N207,Coney Green,51.534156,-0.4588592
+N207,Hayes End,51.5257,-0.4357732
+N207,Hayes By-Pass,51.51593,-0.398889
+N207,"Southall, Town Hall",51.5113272,-0.3751471
+N207,Southall Park,51.5094438,-0.3697251
+N207,Ealing Hospital,51.5075205,-0.3465216
+N207,Ealing Broadway,51.5146192,-0.3022912
+N207,"Acton, High Street",51.5071042,-0.270558
+N207,Acton Vale,51.5065594,-0.2567913
+N207,Shepherd's Bush,51.5051913,-0.22469
+N207,Notting Hill Gate,51.5090534,-0.1966727
+N207,Lancaster Gate,51.5115786,-0.1802482
+N207,Marble Arch,51.5132225,-0.1588937
+N207,Oxford Circus,51.5152543,-0.1420395
+N207,Holborn,51.5175802,-0.1145147
+N253,Aldgate,51.5134365,-0.0772463
+N253,Ash Grove,51.5358094,-0.0581907
+N253,Hackney Central,51.5482344,-0.05738749999999999
+N253,Clapton Pond,51.5561061,-0.05490830000000001
+N253,Stamford Hill,51.5696514,-0.0750199
+N253,Manor House,51.4309209,-0.0936496
+N253,Finsbury Park Station,51.5646425,-0.1058553
+N253,"Holloway, Nags Head",51.55724250000001,-0.1204364
+N253,"Camden Road, Brecknock Road",51.5488418,-0.1290968
+N253,Camden Town,51.5390261,-0.1425516
+N253,Mornington Crescent,51.5334445,-0.1404782
+N253,Euston,51.5280408,-0.1333271
+N253,Warren Street,51.5240516,-0.1399547
+N253,Tottenham Court Road,51.5203145,-0.1340121
+N279,Waltham Cross,51.68584389999999,-0.0330964
+N279,Enfield Highway,51.652918,-0.041145
+N279,Edmonton Green,51.6248126,-0.0581806
+N279,"Snells Park, Sainsburys",51.609054,-0.0691713
+N279,"Tottenham, Town Hall",51.5872187,-0.0725467
+N279,"Tottenham, Town Hall",51.5872187,-0.0725467
+N279,Manor House,51.4309209,-0.0936496
+N279,Finsbury Park Station,51.5646425,-0.1058553
+N279,Finsbury Park Station,51.5646425,-0.1058553
+N279,"Holloway, Nag's Head",51.55724250000001,-0.1204364
+N279,"Camden Road, Brecknock Road",51.5488418,-0.1290968
+N279,Camden Town,51.5390261,-0.1425516
+N279,Mornington Crescent,51.5334445,-0.1404782
+N279,Warren Street,51.5240516,-0.1399547
+N279,Trafalgar Square,51.508039,-0.128069
+N343,Trafalgar Square,51.508039,-0.128069
+N343,Aldwych,51.5132441,-0.1172819
+N343,London Bridge,51.5078788,-0.0877321
+N343,Elephant & Castle,51.4938058,-0.0977932
+N343,Brockley,51.46377160000001,-0.0366031
+N343,New Cross Gate,51.4749904,-0.0403466
+N381,Peckham,51.47032369999999,-0.0673872
+N381,Rotherhithe,51.49628999999999,-0.0411931
+N381,Waterloo,51.5048541,-0.1136621
+N381,"Whitehall, Horse Guards",51.5049111,-0.1273704
+N550,Trafalgar Square,51.508039,-0.128069
+N550,Aldgate,51.5134365,-0.0772463
+N550,Cannon Street,51.5119949,-0.091962
+N550,"Limehouse, Burdett Road",51.5150014,-0.0285662
+N550,"Poplar, All Saints",51.5105521,-0.0118612
+N550,Canning Town,51.5189494,0.0132
+N551,Trafalgar Square,51.508039,-0.128069
+N551,Aldwych,51.5132441,-0.1172819
+N551,Aldgate,51.5134365,-0.0772463
+N551,Limehouse,51.5110598,-0.0366652
+N551,"Poplar, All Saints",51.5105521,-0.0118612
+N551,Canning Town,51.5189494,0.0132
+N551,Keir Hardie Estate,51.5678758,-0.0607466
+N551,Prince Regent,51.4309209,-0.0936496
+N551,Beckton Station,51.5144016,0.06153319999999999
+N551,"Gallions Reach, Shopping Park",51.5166002,0.0783827
diff --git a/lib/audio_cache.dart b/lib/audio_cache.dart
index a455fc4..ed17ff6 100644
--- a/lib/audio_cache.dart
+++ b/lib/audio_cache.dart
@@ -13,8 +13,15 @@ class AudioCache {
return _audioCache.keys.toList();
}
- Uint8List operator [](String key) {
- return _audioCache[key]!;
+ Uint8List? operator [](String key) {
+ // ignore case
+ key = key.toLowerCase();
+ for (var k in _audioCache.keys) {
+ if (k.toLowerCase() == key) {
+ return _audioCache[k];
+ }
+ }
+ return null;
}
}
@@ -22,7 +29,21 @@ class AnnouncementCache extends AudioCache {
String _assetLocation = "assets/ibus_recordings.zip";
- Future loadAnnouncements(List Announcements) async {
+ Future loadAnnouncements(List announcements) async {
+
+ List _announements = [];
+
+
+ // remove any announcements that are already loaded
+ for (var announcement in announcements) {
+ if (!_audioCache.containsKey(announcement.toLowerCase())) {
+ _announements.add(announcement);
+ }
+ }
+
+ if (_announements.length == 0) {
+ return;
+ }
final bytes = await rootBundle.load(_assetLocation);
final archive = ZipDecoder().decodeBytes(bytes.buffer.asUint8List());
@@ -34,9 +55,9 @@ class AnnouncementCache extends AudioCache {
filename = filename.split("/").last;
}
- if (Announcements.contains(filename)) {
- _audioCache[filename] = file.content;
- print("Loaded announcement: ${filename}");
+ if (_announements.contains(filename)) {
+ _audioCache[filename.toLowerCase()] = file.content;
+ print("Loaded announcement: $filename");
}
}
}
@@ -62,7 +83,7 @@ class AnnouncementCache extends AudioCache {
filename = filename.split("/").last;
}
- _audioCache[filename] = file.content;
+ _audioCache[filename.toLowerCase()] = file.content;
}
print("Done loading all announcements.");
diff --git a/lib/auth/api_constants.dart b/lib/auth/api_constants.dart
index 07afed2..559eb5e 100644
--- a/lib/auth/api_constants.dart
+++ b/lib/auth/api_constants.dart
@@ -8,6 +8,7 @@ class ApiConstants {
static const String MANUAL_Q_COLLECTION_ID = "65de9f2f925562a2eda8";
static const String INFORMATION_Q_COLLECTION_ID = "65de9f1b6282fd209bdb";
static const String DEST_Q_COLLECTION_ID = "65de9ef464bfa5a0693d";
+ static const String COMMANDS_COLLECTION_ID = "65e035c82dbae432bafe";
diff --git a/lib/backend/live_information.dart b/lib/backend/live_information.dart
new file mode 100644
index 0000000..b59de26
--- /dev/null
+++ b/lib/backend/live_information.dart
@@ -0,0 +1,179 @@
+
+// Singleton
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:appwrite/appwrite.dart' as appwrite;
+import 'package:appwrite/models.dart' as models;
+import 'package:bus_infotainment/audio_cache.dart';
+import 'package:bus_infotainment/auth/api_constants.dart';
+import 'package:bus_infotainment/auth/auth_api.dart';
+import 'package:bus_infotainment/backend/modules/announcement.dart';
+import 'package:bus_infotainment/backend/modules/commands.dart';
+import 'package:bus_infotainment/backend/modules/synced_time.dart';
+import 'package:bus_infotainment/backend/modules/tracker.dart';
+import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:bus_infotainment/utils/audio%20wrapper.dart';
+import 'package:bus_infotainment/utils/delegates.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+import 'package:http/http.dart' as http;
+import 'package:ntp/ntp.dart';
+import 'package:permission_handler/permission_handler.dart';
+
+class LiveInformation {
+
+ static final LiveInformation _singleton = LiveInformation._internal();
+
+ factory LiveInformation() {
+ return _singleton;
+ }
+
+ LiveInformation._internal();
+
+ Future initialize() async {
+
+ {
+ // By default, load the bus sequences from the assets
+ print("Loading bus sequences from assets");
+ busSequences = BusSequences.fromCSV(
+ await rootBundle.loadString("assets/datasets/bus-blinds.csv"),
+ await rootBundle.loadString("assets/datasets/bus-sequences.csv")
+ );
+ print("Loaded bus sequences from assets");
+
+ try {
+
+ http.Response response = await http.get(Uri.parse('https://tfl.gov.uk/bus-sequences.csv'));
+
+ busSequences = BusSequences.fromCSV(
+ await rootBundle.loadString("assets/datasets/bus-blinds.csv"),
+ response.body
+ );
+
+ print("Loaded bus sequences from TFL");
+
+ } catch (e) {
+ print("Failed to load bus sequences from TFL. Using local copy.");
+ }
+
+ String sessionID = "test";
+
+ commandModule = CommandModule(sessionID);
+
+ }
+
+ // Initialise modules
+ syncedTimeModule = SyncedTimeModule();
+ announcementModule = AnnouncementModule();
+
+ // Tracker module is not supported on desktop
+ if (defaultTargetPlatform != TargetPlatform.windows || defaultTargetPlatform != TargetPlatform.linux || defaultTargetPlatform != TargetPlatform.macOS) {
+ // Tracker module is not supported on web
+ await Permission.location.request();
+ trackerModule = TrackerModule();
+ }
+ }
+
+ // Auth
+ AuthAPI auth = AuthAPI();
+
+ // Modules
+ late CommandModule commandModule;
+ late BusSequences busSequences;
+ late AnnouncementModule announcementModule;
+ late SyncedTimeModule syncedTimeModule;
+ late TrackerModule trackerModule;
+
+ // Important variables
+ BusRouteVariant? _currentRouteVariant;
+
+ // Events
+ EventDelegate routeVariantDelegate = EventDelegate();
+
+ // Internal methods
+
+
+
+
+
+ Future setRouteVariant_Internal(BusRouteVariant routeVariant) async {
+
+ // Set the current route variant
+ _currentRouteVariant = routeVariant;
+
+ // Let everyone know that the route variant has been set/changed
+ routeVariantDelegate.trigger(routeVariant);
+
+ // Get all of the files that need to be cached
+ List audioFiles = [];
+
+ for (BusRouteStop stop in routeVariant.busStops) {
+ audioFiles.add(stop.getAudioFileName());
+ }
+
+ // Cache/Load the audio files
+ await announcementModule
+ .announcementCache
+ .loadAnnouncements(audioFiles);
+ }
+
+ // Public methods
+
+ BusRouteVariant? getRouteVariant() {
+ return _currentRouteVariant;
+ }
+
+ Future setRouteVariant(BusRouteVariant routeVariant) async {
+ await commandModule.executeCommand(
+ "setroute ${routeVariant.busRoute.routeNumber} ${routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant)}"
+ );
+ }
+
+
+
+
+
+
+
+
+ /*
+ Everything under this will be considered legacy code
+ */
+
+
+
+
+
+}
+
+class AnnouncementQueueEntry {
+ final String displayText;
+ final List audioSources;
+ bool sendToServer = true;
+ DateTime? scheduledTime;
+ DateTime? timestamp;
+
+ AnnouncementQueueEntry({required this.displayText, required this.audioSources, this.sendToServer = true, this.scheduledTime, this.timestamp});
+}
+
+class NamedAnnouncementQueueEntry extends AnnouncementQueueEntry {
+ final String shortName;
+
+ NamedAnnouncementQueueEntry({
+ required this.shortName,
+ required String displayText,
+ required List audioSources,
+ DateTime? scheduledTime,
+ DateTime? timestamp,
+ bool sendToServer = true,
+ }) : super(
+ displayText: displayText,
+ audioSources: audioSources,
+ sendToServer: sendToServer,
+ scheduledTime: scheduledTime,
+ timestamp: timestamp,
+ );
+}
+
+var abs = (int value) => value < 0 ? -value : value;
\ No newline at end of file
diff --git a/lib/backend/modules/announcement.dart b/lib/backend/modules/announcement.dart
new file mode 100644
index 0000000..6d68e89
--- /dev/null
+++ b/lib/backend/modules/announcement.dart
@@ -0,0 +1,330 @@
+
+import 'dart:async';
+import 'dart:typed_data';
+
+import 'package:bus_infotainment/audio_cache.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:bus_infotainment/utils/audio%20wrapper.dart';
+import 'package:bus_infotainment/utils/delegates.dart';
+
+import 'info_module.dart';
+
+class AnnouncementModule extends InfoModule {
+
+ AnnouncementCache announcementCache = AnnouncementCache();
+
+ // Constructor
+ AnnouncementModule() {
+ refreshTimer();
+ }
+
+ // Queue
+ List queue = [];
+ AnnouncementQueueEntry? currentAnnouncement;
+ DateTime? currentAnnouncementTimeStamp;
+ String defaultText = "*** NO MESSAGE ***";
+ bool isPlaying = false;
+
+ // Audio
+ AudioWrapper audioPlayer = AudioWrapper();
+
+ // Events
+ final EventDelegate onAnnouncement = EventDelegate();
+
+ // Timer
+ Timer refreshTimer() => Timer.periodic(const Duration(milliseconds: 200), (timer) async {
+
+ if (!isPlaying) {
+
+ if (queue.isNotEmpty) {
+ isPlaying = true;
+ AnnouncementQueueEntry nextAnnouncement = queue.first;
+
+ bool proceeding = await _internalAccountForInconsistentTime(
+ announcement: nextAnnouncement,
+ timerInterval: const Duration(milliseconds: 200),
+ callback: () {
+ queue.removeAt(0);
+ print("Announcement proceeding");
+ }
+ );
+
+ if (!proceeding) {
+ isPlaying = false;
+ print("Announcement not proceeding");
+ print("Queue: ${queue.length}");
+ return;
+ }
+
+ currentAnnouncement = nextAnnouncement;
+ currentAnnouncementTimeStamp = liveInformation.syncedTimeModule.Now();
+
+ onAnnouncement.trigger(currentAnnouncement!);
+
+ if (currentAnnouncement!.audioSources.isNotEmpty) {
+ try {
+ for (AudioWrapperSource source in currentAnnouncement!.audioSources) {
+
+ await audioPlayer.loadSource(source);
+
+ Duration? duration = await audioPlayer.play();
+ await Future.delayed(duration!);
+ if (currentAnnouncement?.audioSources.last != source) {
+ await Future.delayed(const Duration(milliseconds: 100));
+ }
+ }
+ audioPlayer.stop();
+
+ } catch (e) {
+ // Do nothing
+ print("Error playing announcement: $e");
+ }
+ } else {
+ if (queue.isNotEmpty) {
+ await Future.delayed(const Duration(seconds: 5));
+ }
+ }
+
+ isPlaying = false;
+
+ }
+
+ }
+
+
+ });
+
+ // Will call the callback function if the announcement will be proceeding
+ Future _internalAccountForInconsistentTime({
+ required AnnouncementQueueEntry announcement,
+ required Duration timerInterval,
+ required Function() callback
+ }) async {
+ DateTime now = liveInformation.syncedTimeModule.Now();
+ if (announcement.scheduledTime != null) {
+
+ if (now.isAfter(announcement.scheduledTime!)) {
+ callback();
+ return true;
+ }
+
+ int milisecondDifference = abs(now.millisecondsSinceEpoch - announcement.scheduledTime!.millisecondsSinceEpoch);
+ if (milisecondDifference <= timerInterval.inMilliseconds) {
+ // Account for the time lost by the periodic timer
+ callback();
+ await Future.delayed(Duration(milliseconds: timerInterval.inMilliseconds - milisecondDifference));
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ callback();
+ return true;
+ }
+ }
+
+ // Configuration
+ int get defaultAnnouncementDelay => liveInformation.auth.isAuthenticated() ? 2 : 0;
+
+ // Methods
+ Future queueAnnounceByAudioName({
+ required String displayText,
+ List audioNames = const [],
+ DateTime? scheduledTime = null,
+ bool sendToServer = true
+ }) async {
+
+ if (sendToServer) {
+
+ scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
+
+ String audioNamesString = "";
+
+ for (var audioName in audioNames) {
+ audioNamesString += "\"$audioName\" ";
+ }
+
+ liveInformation.commandModule.executeCommand(
+ "announce manual \"$displayText\" ${audioNamesString} ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
+ );
+
+ return;
+ }
+
+ // Cache the announcements
+ await announcementCache.loadAnnouncements(audioNames);
+
+ List sources = [];
+
+ print("Audio names: $audioNames");
+
+ for (var audioName in audioNames) {
+ Uint8List? audioData = announcementCache[audioName];
+
+ if (audioData == null) {
+ continue;
+ }
+
+ sources.add(AudioWrapperByteSource(audioData));
+
+ }
+
+ queue.add(
+ AnnouncementQueueEntry(
+ displayText: displayText,
+ audioSources: sources,
+ scheduledTime: scheduledTime
+ )
+ );
+
+ }
+
+ void queueAnnounementByInfoIndex({
+ int infoIndex = -1,
+ DateTime? scheduledTime = null,
+ bool sendToServer = true
+ }) {
+
+ if (sendToServer) {
+
+ scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
+
+ liveInformation.commandModule.executeCommand(
+ "announce info $infoIndex ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
+ );
+ return;
+ }
+
+ NamedAnnouncementQueueEntry clone = NamedAnnouncementQueueEntry(
+ shortName: manualAnnouncements[infoIndex].shortName,
+ displayText: manualAnnouncements[infoIndex].displayText,
+ audioSources: manualAnnouncements[infoIndex].audioSources,
+ scheduledTime: scheduledTime
+ );
+
+ queue.add(clone);
+ }
+
+ Future queueAnnouncementByRouteVariant({
+ required BusRouteVariant routeVariant,
+ DateTime? scheduledTime = null,
+ bool sendToServer = true
+ }) async {
+
+ if (sendToServer) {
+
+ scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
+
+ liveInformation.commandModule.executeCommand(
+ "announce dest \"${routeVariant.busRoute.routeNumber}\" ${routeVariant.busRoute.routeVariants.values.toList().indexOf(routeVariant)} ${scheduledTime?.millisecondsSinceEpoch ?? ""}"
+ );
+ return;
+ }
+
+ String routeNumber = routeVariant.busRoute.routeNumber;
+ String destination = routeVariant.destination!.destination;
+
+ String audioRoute = "R_${routeVariant.busRoute.routeNumber}_001.mp3";
+
+ await announcementCache.loadAnnouncements([audioRoute]);
+
+ AudioWrapperSource sourceRoute = AudioWrapperByteSource(announcementCache[audioRoute]!);
+ AudioWrapperSource sourceDestination = AudioWrapperByteSource(await routeVariant.destination!.getAudioBytes());
+
+ AnnouncementQueueEntry announcement = AnnouncementQueueEntry(
+ displayText: "$routeNumber to $destination",
+ audioSources: [sourceRoute, AudioWrapperAssetSource("audio/to_destination.wav"), sourceDestination],
+ scheduledTime: scheduledTime
+ );
+
+ queue.add(announcement);
+ }
+
+ // Constants
+
+ final List manualAnnouncements = [
+ NamedAnnouncementQueueEntry(
+ shortName: "Driver Change",
+ displayText: "Driver Change",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/driverchange.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "No Standing Upr Deck",
+ displayText: "No standing on the upper deck",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nostanding.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Face Covering",
+ displayText: "Please wear a face covering!",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/facecovering.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Seats Upstairs",
+ displayText: "Seats are available upstairs",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/seatsupstairs.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Bus Terminates Here",
+ displayText: "Bus terminates here. Please take your belongings with you",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busterminateshere.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Bus On Diversion",
+ displayText: "Bus on diversion. Please listen for further announcements",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busondiversion.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Destination Change",
+ displayText: "Destination Changed - please listen for further instructions",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/destinationchange.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Wheelchair Space",
+ displayText: "Wheelchair space requested",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace1.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Move Down The Bus",
+ displayText: "Please move down the bus",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/movedownthebus.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Next Stop Closed",
+ displayText: "The next bus stop is closed",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nextstopclosed.wav")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "CCTV In Operation",
+ displayText: "CCTV is in operation on this bus",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/cctvoperation.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Safe Door Opening",
+ displayText: "Driver will open the doors when it is safe to do so",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/safedooropening.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Buggy Safety",
+ displayText: "For your child's safety, please remain with your buggy",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/buggysafety.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Wheelchair Space 2",
+ displayText: "Wheelchair priority space required",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace2.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Service Regulation",
+ displayText: "Regulating service - please listen for further information",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/serviceregulation.mp3")],
+ ),
+ NamedAnnouncementQueueEntry(
+ shortName: "Bus Ready To Depart",
+ displayText: "This bus is ready to depart",
+ audioSources: [AudioWrapperAssetSource("audio/manual_announcements/readytodepart.mp3")],
+ ),
+ ];
+
+
+}
\ No newline at end of file
diff --git a/lib/backend/modules/commands.dart b/lib/backend/modules/commands.dart
new file mode 100644
index 0000000..516ec20
--- /dev/null
+++ b/lib/backend/modules/commands.dart
@@ -0,0 +1,224 @@
+
+import 'dart:convert';
+
+import 'package:bus_infotainment/auth/api_constants.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:bus_infotainment/utils/audio%20wrapper.dart';
+import 'package:bus_infotainment/utils/delegates.dart';
+import 'package:appwrite/appwrite.dart' as appwrite;
+import 'package:appwrite/models.dart' as models;
+import 'package:uuid/uuid.dart';
+
+import '../../auth/auth_api.dart';
+import 'info_module.dart';
+
+class CommandModule extends InfoModule {
+
+ final String sessionID;
+ late final String clientID;
+
+ List _commandHistory = [];
+ get commandHistory => _commandHistory;
+ EventDelegate onCommandReceived = EventDelegate();
+
+ CommandModule(this.sessionID){
+ // generate a random client ID
+ var uuid = Uuid();
+
+ clientID = uuid.v4();
+
+ if (liveInformation.auth.isAuthenticated()){
+ print("Auth is authenticated");
+ _setupListener();
+ } else {
+ print("Auth is not authenticated");
+ liveInformation.auth.onLogin.addListener((value) {
+ _setupListener();
+ });
+ }
+ }
+
+ // Will execute the command an event which is triggered when a response is received
+ Future executeCommand(String command) async {
+ EventDelegate delegate = EventDelegate();
+
+ final client = liveInformation.auth.client;
+
+ final databases = appwrite.Databases(client);
+
+ if (liveInformation.auth.status == AuthStatus.AUTHENTICATED) {
+ final document = await databases.createDocument(
+ databaseId: ApiConstants.INFO_Q_DATABASE_ID,
+ collectionId: ApiConstants.COMMANDS_COLLECTION_ID,
+ documentId: appwrite.ID.unique(),
+ data: {
+ "session_id": sessionID,
+ "command": command,
+ "client_id": clientID,
+ }
+ );
+ }
+
+ _onCommandReceived(CommandInfo(command, clientID));
+
+ return delegate;
+ }
+
+ Future _onCommandReceived(CommandInfo commandInfo) async {
+
+ commandHistory.add(commandInfo);
+ onCommandReceived.trigger(commandInfo);
+
+ print("Received command: ${commandInfo.command}");
+
+ List commandParts = splitCommand(commandInfo.command);
+ String command = commandParts[0];
+ List args = commandParts.sublist(1);
+
+ if (command == "Response:") {
+
+ }
+ else if (command == "announce") {
+
+ final displayText = args[1];
+
+ if (args[0] == "manual") {
+ // announce manual ...
+
+
+ List audioFileNames = args.sublist(2);
+ try {
+ if (int.parse(audioFileNames.last) != null) {
+ audioFileNames.removeLast();
+ }
+ } catch (e) {}
+
+ DateTime scheduledTime = LiveInformation().syncedTimeModule.Now().add(Duration(seconds: 1));
+ try {
+ if (int.parse(args.last) != null) {
+ scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
+ }
+ } catch (e) {}
+
+ liveInformation.announcementModule.queueAnnounceByAudioName(
+ displayText: displayText,
+ audioNames: audioFileNames,
+ scheduledTime: scheduledTime,
+ sendToServer: false
+ );
+
+ }
+ else if (args[0] == "info") {
+
+ int InfoIndex = int.parse(args[1]);
+
+ DateTime scheduledTime = LiveInformation().syncedTimeModule.Now();
+ try {
+ if (int.parse(args.last) != null) {
+ scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
+ }
+ } catch (e) {}
+
+ liveInformation.announcementModule.queueAnnounementByInfoIndex(
+ infoIndex: InfoIndex,
+ scheduledTime: scheduledTime,
+ sendToServer: false
+ );
+ }
+ else if (args[0].startsWith("dest")) {
+ // announce destination
+
+ String routeNumber = args[1];
+ int routeVariantIndex = int.parse(args[2]);
+
+ DateTime scheduledTime = LiveInformation().syncedTimeModule.Now();
+ try {
+ if (int.parse(args.last) != null) {
+ scheduledTime = DateTime.fromMillisecondsSinceEpoch(int.parse(args.last));
+ }
+ } catch (e) {}
+
+ BusRoute route = LiveInformation().busSequences.routes[routeNumber]!;
+ BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
+
+ liveInformation.announcementModule.queueAnnouncementByRouteVariant(
+ routeVariant: routeVariant,
+ scheduledTime: scheduledTime,
+ sendToServer: false
+ );
+
+ }
+
+ }
+ else if (command == "setroute") {
+ // setroute
+
+ LiveInformation liveInformation = LiveInformation();
+
+ String routeNumber = args[0];
+ int routeVariantIndex = int.parse(args[1]);
+
+ BusRoute route = liveInformation.busSequences.routes[routeNumber]!;
+ BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
+
+ liveInformation.setRouteVariant_Internal(
+ routeVariant
+ );
+ executeCommand("Response: v \"Client $clientID set its route to ($routeNumber to ${routeVariant.busStops.last.formattedStopName})\"");
+
+ }
+
+ }
+
+ appwrite.RealtimeSubscription? _subscription;
+ Future _setupListener() async {
+ if (_subscription != null) {
+ return;
+ }
+
+ final realtime = appwrite.Realtime(LiveInformation().auth.client);
+
+ _subscription = realtime.subscribe(
+ ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.COMMANDS_COLLECTION_ID}.documents']
+ );
+ _subscription!.stream.listen((event) {
+ print(jsonEncode(event.payload));
+
+ // Only do something if the document was created or updated
+ if (!(event.events.first.contains("create") || event.events.first.contains("update"))) {
+ return;
+ }
+
+ final commandInfo = CommandInfo(event.payload['command'], event.payload['client_id']);
+
+ if (commandInfo.clientID != clientID) {
+ _onCommandReceived(commandInfo);
+ }
+
+ });
+
+ print("Listening for commands");
+
+ await Future.delayed(Duration(seconds: 90));
+
+ await _subscription!.close();
+ _subscription = null;
+ _setupListener();
+
+ }
+
+}
+
+class CommandInfo {
+ final String command;
+ final String clientID;
+
+ CommandInfo(this.command, this.clientID);
+}
+
+List splitCommand(String command) {
+ var regex = RegExp(r'([^\s"]+)|"([^"]*)"');
+ var matches = regex.allMatches(command);
+ return matches.map((match) => match.group(0)!.replaceAll('"', '')).toList();
+}
\ No newline at end of file
diff --git a/lib/backend/modules/info_module.dart b/lib/backend/modules/info_module.dart
new file mode 100644
index 0000000..2ea7012
--- /dev/null
+++ b/lib/backend/modules/info_module.dart
@@ -0,0 +1,8 @@
+
+import 'package:bus_infotainment/backend/live_information.dart';
+
+abstract class InfoModule {
+
+ LiveInformation get liveInformation => LiveInformation();
+
+}
\ No newline at end of file
diff --git a/lib/backend/modules/synced_time.dart b/lib/backend/modules/synced_time.dart
new file mode 100644
index 0000000..7b7ae92
--- /dev/null
+++ b/lib/backend/modules/synced_time.dart
@@ -0,0 +1,36 @@
+
+import 'dart:async';
+import 'dart:convert';
+import 'package:http/http.dart' as http;
+
+import 'info_module.dart';
+
+class SyncedTimeModule extends InfoModule {
+
+ int timeOffset = -1;
+ DateTime lastUpdate = DateTime.now().add(const Duration(seconds: -15));
+
+ SyncedTimeModule() {
+ refreshTimer();
+ }
+
+ Timer refreshTimer() => Timer.periodic(const Duration(seconds: 10), (timer) async {
+ var res = await http.get(Uri.parse('http://worldtimeapi.org/api/timezone/Europe/London'));
+ if (res.statusCode == 200) {
+ var json = jsonDecode(res.body);
+ DateTime time = DateTime.parse(json['datetime']);
+ timeOffset = time.millisecondsSinceEpoch - DateTime.now().millisecondsSinceEpoch;
+ lastUpdate = DateTime.now();
+ print("Time offset: $timeOffset");
+ } else {
+ print("Failed to get time from worldtimeapi.org");
+ }
+ });
+
+ DateTime Now() {
+ if (timeOffset == -1) {
+ return DateTime.now();
+ }
+ return DateTime.now().add(Duration(milliseconds: timeOffset));
+ }
+}
\ No newline at end of file
diff --git a/lib/backend/modules/tracker.dart b/lib/backend/modules/tracker.dart
new file mode 100644
index 0000000..96123aa
--- /dev/null
+++ b/lib/backend/modules/tracker.dart
@@ -0,0 +1,199 @@
+
+import 'dart:async';
+import 'dart:math';
+import 'dart:typed_data';
+
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/backend/modules/info_module.dart';
+import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
+import 'package:bus_infotainment/utils/audio%20wrapper.dart';
+import 'package:geolocator/geolocator.dart';
+import 'package:vector_math/vector_math.dart';
+
+class TrackerModule extends InfoModule {
+
+
+ TrackerModule() {
+ locationStream();
+ Geolocator.getLastKnownPosition().then((Position? position) {
+ this._position = position;
+ updateNearestStop();
+ });
+ liveInformation.routeVariantDelegate.addListener((routeVariant) {
+ print("Route variant changed");
+ updateNearestStop();
+ });
+ }
+
+
+ Position? _position;
+ Position? get position => _position;
+
+ StreamSubscription locationStream() => Geolocator.getPositionStream(
+ locationSettings: const LocationSettings(
+ accuracy: LocationAccuracy.high,
+ distanceFilter: 1,
+ )
+ ).listen((Position position) {
+
+ if (position == null) {
+ return;
+ }
+
+ this._position = position;
+ updateNearestStop();
+ });
+
+ Timer refreshTimer() => Timer.periodic(Duration(seconds: 1), (timer) async {
+ _position = await Geolocator.getCurrentPosition();
+ });
+
+ BusRouteStop? nearestStop;
+ bool hasArrived = false;
+
+ Future updateNearestStop() async {
+ if (liveInformation.getRouteVariant() == null) {
+ return;
+ }
+
+ // Get the closest stop
+ BusRouteStop closestStop = liveInformation.getRouteVariant()!.busStops.first;
+ double closestDistance = OSGrid
+ .toNorthingEasting(_position!.latitude, _position!.longitude)
+ .distanceTo(Vector2(closestStop.easting.toDouble(), closestStop.northing.toDouble()));
+
+ for (BusRouteStop stop in liveInformation.getRouteVariant()!.busStops) {
+ double distance = OSGrid
+ .toNorthingEasting(_position!.latitude, _position!.longitude)
+ .distanceTo(Vector2(stop.easting.toDouble(), stop.northing.toDouble()));
+
+ if (distance < closestDistance) {
+ closestStop = stop;
+ closestDistance = distance;
+ }
+ }
+
+ double relativeDistance = _calculateRelativeDistance(closestStop, _position!.latitude, _position!.longitude);
+
+
+
+ if (relativeDistance < -10) {
+ print("Closest stop is behind us: ${closestStop.formattedStopName}");
+ print("Relative distance: $relativeDistance");
+
+ int stopIndex = liveInformation.getRouteVariant()!.busStops.indexOf(closestStop);
+
+ closestStop = liveInformation.getRouteVariant()!.busStops[stopIndex + 1];
+
+ print("Closest stop is now: ${closestStop.formattedStopName}");
+ } else {
+ print("Closest stop is in front of us: ${closestStop.formattedStopName}");
+ }
+
+ bool preExisting = true;
+
+ if (nearestStop != closestStop) {
+ nearestStop = closestStop;
+ hasArrived = false;
+ preExisting = false;
+ }
+
+ print("Closest stop is the same as before");
+
+ double distance = OSGrid
+ .toNorthingEasting(_position!.latitude, _position!.longitude)
+ .distanceTo(Vector2(nearestStop!.easting.toDouble(), nearestStop!.northing.toDouble()));
+
+ // get the speed in mph
+ double speed = _position!.speed * 2.23694;
+ print("Speed: $speed");
+
+ Duration? duration;
+ {
+ // Testing some audio stuff
+ Uint8List? audioBytes = liveInformation.announcementModule.announcementCache[nearestStop!.getAudioFileName()];
+ AudioWrapperByteSource audioSource = AudioWrapperByteSource(audioBytes!);
+
+ AudioWrapper audio = AudioWrapper();
+
+ await audio.loadSource(audioSource);
+
+ duration = await audio.getDuration();
+
+ print("Duration of audio: $duration");
+ }
+
+ // get the estimated distance travelled in 5 seconds, in meters
+ double distanceTravelled = speed * (3 + duration!.inSeconds);
+
+ // adjust for the it takes to send the announcement to other devices
+ distance -= distanceTravelled;
+
+ // get the time to the stop in seconds
+ double timeToStop = distance / speed;
+
+ print("Distance to stop: $distance");
+ print("Time to stop: $timeToStop");
+
+ int secondsBefore = 7;
+
+ print("Seconds before: $secondsBefore");
+
+ if ((timeToStop < secondsBefore ) && !hasArrived && relativeDistance > 0) {
+ print("We are at the stop");
+ hasArrived = true;
+ liveInformation.announcementModule.queueAnnounceByAudioName(
+ displayText: "${nearestStop!.formattedStopName}",
+ audioNames: [
+ // "A_NEXT_STOP_001.mp3",
+ nearestStop!.getAudioFileName()
+ ],
+ sendToServer: true
+ );
+ }
+
+
+ if (!hasArrived && !preExisting) {
+ liveInformation.announcementModule.queueAnnounceByAudioName(
+ displayText: "${closestStop.formattedStopName}",
+ audioNames: [],
+ sendToServer: true
+ );
+ }
+
+
+
+ print("Closest stop: ${closestStop.formattedStopName} in ${closestDistance.round()} meters");
+ }
+
+
+}
+
+double _calculateRelativeDistance(BusRouteStop stop, double latitude, double longitude) {
+
+ List toLatLong = OSGrid.toLatLong(stop.northing.toDouble(), stop.easting.toDouble());
+
+ Vector2 stopPoint = OSGrid.toNorthingEasting(toLatLong[0], toLatLong[1]);
+ Vector2 currentPoint = OSGrid.toNorthingEasting(latitude, longitude);
+
+ // calculate the heading from the current point to the stop point
+ // 0 degrees is north, 90 degrees is east, 180 degrees is south, 270 degrees is west
+ double toHeading = degrees(atan2(stopPoint.x - currentPoint.x, stopPoint.y - currentPoint.y));
+ toHeading = (toHeading + 360) % 360;
+
+ // get the dot product of the heading and the stop heading
+ double dotProduct = cos(radians(toHeading)) * cos(radians(stop.heading.toDouble())) + sin(radians(toHeading)) * sin(radians(stop.heading.toDouble()));
+
+ return (dotProduct.sign) * _calculateDistance(latitude, longitude, toLatLong[0], toLatLong[1]);
+}
+
+double _calculateDistance(double lat1, double lon1, double lat2, double lon2) {
+
+ // Convert to eastings and northings
+ Vector2 point1 = OSGrid.toNorthingEasting(lat1, lon1);
+ Vector2 point2 = OSGrid.toNorthingEasting(lat2, lon2);
+
+ return point1.distanceTo(point2);
+
+}
\ No newline at end of file
diff --git a/lib/main.dart b/lib/main.dart
index 92ff6fd..58ed02d 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -2,15 +2,32 @@ import 'dart:io';
import 'package:bus_infotainment/pages/audio_cache_test.dart';
import 'package:bus_infotainment/pages/tfl_dataset_test.dart';
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:window_manager/window_manager.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
+ if (defaultTargetPlatform == TargetPlatform.windows && !kIsWeb) {
+ await windowManager.ensureInitialized();
+
+ WindowOptions options = WindowOptions(
+ size: Size(411.4, 850.3),
+ );
+
+ windowManager.setAspectRatio(411.4 / 850.3);
+
+ await windowManager.waitUntilReadyToShow(options, () async {
+ await windowManager.show();
+ await windowManager.focus();
+ });
+ }
+
LiveInformation liveInformation = LiveInformation();
- await liveInformation.Initialize();
+ await liveInformation.initialize();
// Disalow screen to turn off on android
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
@@ -30,6 +47,10 @@ class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
+
+ // Permission.location.onGrantedCallback(() => null).request();
+
+ print("Window size: ${MediaQuery.of(context).size}");
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
diff --git a/lib/pages/components/ibus_display.dart b/lib/pages/components/ibus_display.dart
index cd5dfd7..99693a4 100644
--- a/lib/pages/components/ibus_display.dart
+++ b/lib/pages/components/ibus_display.dart
@@ -1,9 +1,10 @@
import 'dart:async';
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/utils/delegates.dart';
import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
import 'package:text_scroll/text_scroll.dart';
class ibus_display extends StatefulWidget {
@@ -21,13 +22,14 @@ class ibus_display extends StatefulWidget {
class _ibus_displayState extends State {
String topLine = "*** NO MESSAGE ***";
+ String bottomLine = "";
late final ListenerReceipt _receipt;
_ibus_displayState(){
LiveInformation liveInformation = LiveInformation();
- _receipt = liveInformation.announcementDelegate.addListener((value) {
+ _receipt = liveInformation.announcementModule.onAnnouncement.addListener((value) {
if (topLine == value.displayText){
return;
@@ -38,7 +40,7 @@ class _ibus_displayState extends State {
});
});
- topLine = liveInformation.currentAnnouncement;
+ topLine = liveInformation.announcementModule.currentAnnouncement?.displayText ?? liveInformation.announcementModule.defaultText;
}
@@ -55,6 +57,8 @@ class _ibus_displayState extends State {
prefix += " ";
}
+ input = input.replaceAll("©", "(c)");
+
return prefix + input + suffix;
}
@@ -62,7 +66,7 @@ class _ibus_displayState extends State {
@override
void dispose() {
- LiveInformation().announcementDelegate.removeListener(_receipt);
+ LiveInformation().announcementModule.onAnnouncement.removeListener(_receipt);
super.dispose();
@@ -75,19 +79,45 @@ class _ibus_displayState extends State {
return Container(
width: double.infinity,
+ color: Colors.black,
child: FittedBox(
alignment: Alignment.center,
child: Stack(
children: [
+
+ Positioned.fill(
+ child: Container(
+
+ alignment: Alignment.bottomCenter,
+
+ margin: EdgeInsets.all(1),
+
+ child: Text(
+ "© ImBenji.net - all rights reserved | © Transport for London - all rights reserved",
+ style: GoogleFonts.teko(
+ fontSize: 10,
+ color: Colors.white.withOpacity(0.01),
+ height: 1,
+ shadows: [
+ Shadow(
+ color: Colors.black,
+ blurRadius: 5,
+ )
+ ]
+ )
+ ),
+
+ ),
+ ),
+
Container(
// width: double.infinity,
// height: 100,
decoration: BoxDecoration(
- color: Colors.black,
border: widget.hasBorder ? Border.all(color: Colors.grey.shade900, width: 2) : null,
),
@@ -127,17 +157,27 @@ class _ibus_displayState extends State {
),
Transform.translate(
- offset: Offset(0, -7),
- child: Text(
- "",
- style: const TextStyle(
- fontSize: 20,
- color: Colors.orange,
- fontFamily: "ibus",
- height: 1.5
+ offset: Offset(0, -6),
+ child: Container(
+ alignment: Alignment.center,
+ width: 32*4*3,
+ child: TextScroll(
+ _padString(bottomLine),
+ velocity: Velocity(pixelsPerSecond: Offset(120, 0)),
+ style: const TextStyle(
+ fontSize: 20,
+ color: Colors.orange,
+ fontFamily: "ibus",
+ shadows: [
+ Shadow(
+ color: Colors.orange,
+ blurRadius: 5,
+ ),
+ ],
+ ),
),
),
- )
+ ),
],
),
),
@@ -145,6 +185,8 @@ class _ibus_displayState extends State {
),
+
+
Positioned.fill(
child: Container(
decoration: BoxDecoration(
diff --git a/lib/pages/display.dart b/lib/pages/display.dart
index 20995ff..144fd60 100644
--- a/lib/pages/display.dart
+++ b/lib/pages/display.dart
@@ -3,6 +3,7 @@ import 'package:bus_infotainment/pages/components/ibus_display.dart';
import 'package:bus_infotainment/pages/tfl_dataset_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:google_fonts/google_fonts.dart';
class pages_Display extends StatefulWidget {
@@ -30,23 +31,29 @@ class _pages_DisplayState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
+ Expanded(
+ child: RotatedBox(
+ quarterTurns: 1,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ ibus_display(
+ hasBorder: false,
+ ),
- if (MediaQuery.of(context).size.width < 600)
- Expanded(
- child: RotatedBox(
- quarterTurns: 1,
- child: ibus_display(
- hasBorder: false,
- ),
- ),
- )
- else
- Expanded(
- child: ibus_display(
- hasBorder: false,
+ if (widget._tfL_Dataset_TestState.hideUI)
+ Container(
+ alignment: Alignment.bottomLeft,
+ height: double.infinity,
+ width: double.infinity,
+
+ margin: EdgeInsets.all(5),
+
+ )
+ ],
),
),
-
+ )
],
),
),
diff --git a/lib/pages/home.dart b/lib/pages/home.dart
index 70eacf0..285995b 100644
--- a/lib/pages/home.dart
+++ b/lib/pages/home.dart
@@ -1,11 +1,15 @@
+import 'dart:async';
+
import 'package:bus_infotainment/pages/components/ibus_display.dart';
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:bus_infotainment/utils/audio%20wrapper.dart';
import 'package:bus_infotainment/utils/delegates.dart';
import 'package:flutter/material.dart';
+import 'package:geolocator/geolocator.dart';
import 'package:google_fonts/google_fonts.dart';
class pages_Home extends StatelessWidget {
@@ -18,226 +22,343 @@ class pages_Home extends StatelessWidget {
- child: SingleChildScrollView(
- child: Column(
- children: [
-
- Container(
- height: 2,
- color: Colors.white70,
- ),
-
- Container(
-
- decoration: BoxDecoration(
- color: Colors.grey.shade900,
- boxShadow: [
- BoxShadow(
- color: Colors.black.withOpacity(0.3),
- blurRadius: 2,
- spreadRadius: 4
- )
- ]
- ),
-
- margin: EdgeInsets.all(20),
-
- child: ibus_display(),
-
- ),
-
- Container(
- height: 2,
- color: Colors.white70,
- ),
-
- Container(
-
- margin: EdgeInsets.all(20),
-
- child: Container(
-
- decoration: BoxDecoration(
- color: Colors.grey.shade900,
- boxShadow: [
- BoxShadow(
- color: Colors.black.withOpacity(0.3),
- blurRadius: 2,
- spreadRadius: 4
- )
- ]
- ),
-
- child: ManualAnnouncementPicker(
- backgroundColor: Colors.grey.shade900,
- outlineColor: Colors.white70,
- announcements: [
- ...LiveInformation().manualAnnouncements
- ],
- ),
- ),
-
- ),
-
- Container(
- height: 2,
- color: Colors.white70,
- ),
-
- Container(
-
- margin: EdgeInsets.all(20),
-
- child: Container(
-
- decoration: BoxDecoration(
- color: Colors.grey.shade900,
- boxShadow: [
- BoxShadow(
- color: Colors.black.withOpacity(0.3),
- blurRadius: 2,
- spreadRadius: 4
- )
- ]
- ),
-
- child: DelegateBuilder(
- delegate: LiveInformation().routeVariantDelegate,
- builder: (context, routeVariant) {
- print("rebuilt stop announcement picker");
- return StopAnnouncementPicker(
- routeVariant: routeVariant,
+ child: Column(
+ children: [
+
+ Row(
+
+ children: [
+
+ Speedometer(),
+
+ ],
+
+ ),
+
+ Container(
+ height: 2,
+ color: Colors.white70,
+ ),
+
+ SingleChildScrollView(
+ child: Column(
+ children: [
+
+ Container(
+
+ margin: EdgeInsets.all(10),
+
+ child: Container(
+
+ decoration: BoxDecoration(
+ color: Colors.grey.shade900,
+ ),
+
+ child: AnnouncementPicker(
backgroundColor: Colors.grey.shade900,
outlineColor: Colors.white70,
- );
- },
- defaultBuilder: (context) {
- BusRouteVariant? routeVariant = LiveInformation().getRouteVariant();
- if (routeVariant == null) {
- return Container(
- color: Colors.grey.shade900,
- child: Center(
- child: Text(
- "No route selected",
- style: GoogleFonts.teko(
- fontSize: 25,
- color: Colors.white70
- ),
- ),
- ),
- );
- } else {
- return StopAnnouncementPicker(
- routeVariant: routeVariant,
- backgroundColor: Colors.grey.shade900,
- outlineColor: Colors.white70,
- );
- }
- },
+ announcements: [
+ for (NamedAnnouncementQueueEntry announcement in LiveInformation().announcementModule.manualAnnouncements)
+ _AnnouncementEntry(
+ label: announcement.shortName,
+ index: LiveInformation().announcementModule.manualAnnouncements.indexOf(announcement),
+ outlineColor: Colors.white70,
+ onPressed: (){
+ LiveInformation liveInformation = LiveInformation();
+ liveInformation.announcementModule.queueAnnounementByInfoIndex(
+ infoIndex: liveInformation.announcementModule.manualAnnouncements.indexOf(announcement),
+ sendToServer: true
+ );
+ },
+ )
+ ],
+ ),
+ ),
+
),
- ),
-
+
+ Container(
+ height: 2,
+ color: Colors.white70,
+ ),
+
+ Container(
+
+ margin: EdgeInsets.all(10),
+
+ child: Container(
+ decoration: BoxDecoration(
+ color: Colors.grey.shade900,
+ ),
+
+ child: DelegateBuilder(
+ delegate: LiveInformation().routeVariantDelegate,
+ builder: (context, routeVariant) {
+ print("rebuilt stop announcement picker");
+ return StopAnnouncementPicker(
+ routeVariant: routeVariant,
+ backgroundColor: Colors.grey.shade900,
+ outlineColor: Colors.white70,
+ );
+ },
+ defaultBuilder: (context) {
+ BusRouteVariant? routeVariant = LiveInformation().getRouteVariant();
+ if (routeVariant == null) {
+ return Container(
+ color: Colors.grey.shade900,
+ child: Center(
+ child: Text(
+ "No route selected",
+ style: GoogleFonts.teko(
+ fontSize: 25,
+ color: Colors.white70
+ ),
+ ),
+ ),
+ );
+ } else {
+ return StopAnnouncementPicker(
+ routeVariant: routeVariant,
+ backgroundColor: Colors.grey.shade900,
+ outlineColor: Colors.white70,
+ );
+ }
+ },
+ ),
+ ),
+
+ ),
+
+ ElevatedButton(
+ onPressed: () async {
+ LiveInformation liveInformation = LiveInformation();
+ final commandModule = liveInformation.commandModule;
+
+ // commandModule.executeCommand(
+ // "announce dest"
+ // );
+
+ liveInformation.announcementModule.queueAnnouncementByRouteVariant(
+ routeVariant: liveInformation.getRouteVariant()!
+ );
+
+ },
+ child: Text("Announce current destination"),
+ ),
+
+
+ // Container(
+ //
+ // margin: EdgeInsets.all(20),
+ //
+ // height: 300-45,
+ //
+ // child: ListView(
+ //
+ // scrollDirection: Axis.vertical,
+ //
+ // children: [
+ //
+ // ElevatedButton(
+ // onPressed: () async {
+ // LiveInformation liveInformation = LiveInformation();
+ // liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false));
+ // },
+ // child: Text("Test announcement"),
+ // ),
+ //
+ // ElevatedButton(
+ // onPressed: () {
+ // LiveInformation liveInformation = LiveInformation();
+ // liveInformation.updateServer();
+ // },
+ // child: Text("Update server"),
+ // ),
+ //
+ // SizedBox(
+ //
+ // width: 100,
+ //
+ // child: TextField(
+ // onChanged: (String value) {
+ // LiveInformation liveInformation = LiveInformation();
+ // // liveInformation.documentID = value;
+ // },
+ // ),
+ // ),
+ //
+ // SizedBox(
+ //
+ // width: 200,
+ //
+ // child: TextField(
+ // onSubmitted: (String value) {
+ // LiveInformation liveInformation = LiveInformation();
+ // liveInformation.queueAnnouncement(AnnouncementQueueEntry(
+ // displayText: value,
+ // audioSources: []
+ // ));
+ // },
+ // ),
+ // ),
+ //
+ // ElevatedButton(
+ // onPressed: () {
+ // LiveInformation liveInformation = LiveInformation();
+ // liveInformation.pullServer();
+ // },
+ // child: Text("Pull server"),
+ // ),
+ //
+ // ],
+ //
+ // ),
+ //
+ // ),
+
+ ],
),
-
- ElevatedButton(
- onPressed: () async {
- LiveInformation liveInformation = LiveInformation();
- liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: true));
- },
- child: Text("Announce Destination"),
- ),
-
-
- // Container(
- //
- // margin: EdgeInsets.all(20),
- //
- // height: 300-45,
- //
- // child: ListView(
- //
- // scrollDirection: Axis.vertical,
- //
- // children: [
- //
- // ElevatedButton(
- // onPressed: () async {
- // LiveInformation liveInformation = LiveInformation();
- // liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false));
- // },
- // child: Text("Test announcement"),
- // ),
- //
- // ElevatedButton(
- // onPressed: () {
- // LiveInformation liveInformation = LiveInformation();
- // liveInformation.updateServer();
- // },
- // child: Text("Update server"),
- // ),
- //
- // SizedBox(
- //
- // width: 100,
- //
- // child: TextField(
- // onChanged: (String value) {
- // LiveInformation liveInformation = LiveInformation();
- // // liveInformation.documentID = value;
- // },
- // ),
- // ),
- //
- // SizedBox(
- //
- // width: 200,
- //
- // child: TextField(
- // onSubmitted: (String value) {
- // LiveInformation liveInformation = LiveInformation();
- // liveInformation.queueAnnouncement(AnnouncementQueueEntry(
- // displayText: value,
- // audioSources: []
- // ));
- // },
- // ),
- // ),
- //
- // ElevatedButton(
- // onPressed: () {
- // LiveInformation liveInformation = LiveInformation();
- // liveInformation.pullServer();
- // },
- // child: Text("Pull server"),
- // ),
- //
- // ],
- //
- // ),
- //
- // ),
-
- ],
- ),
+ ),
+ ],
)
);
}
}
-class ManualAnnouncementPicker extends StatefulWidget {
+class Speedometer extends StatefulWidget {
+
+ @override
+ State createState() => _SpeedometerState();
+}
+
+
+
+class _SpeedometerState extends State {
+
+ double speed = 0;
+ double arrivalTime = 0;
+
+ BusRouteStop? nearestStop;
+ double speed2 = 0;
+
+ _SpeedometerState(){
+
+
+
+ }
+
+ @override
+ void initState() {
+ // TODO: implement initState
+ super.initState();
+
+ Timer.periodic(Duration(milliseconds: 250), (timer) {
+
+ Position? newPosition = LiveInformation().trackerModule.position;
+
+ speed = newPosition?.speed ?? 0;
+
+ arrivalTime -= 0.25;
+ arrivalTime = arrivalTime < 0 ? 0 : arrivalTime;
+
+ setState(() {
+
+ });
+ });
+
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ // TODO: implement build
+ return Container(
+
+ margin: EdgeInsets.all(8),
+
+ height: 74,
+
+ child: Row(
+ children: [
+ Container(
+ // width: 60,
+ height: double.infinity,
+ alignment: Alignment.center,
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: Colors.white70,
+ width: 2
+ )
+ ),
+ padding: const EdgeInsets.all(8),
+ child: Column(
+
+ mainAxisSize: MainAxisSize.min,
+
+ children: [
+
+ Container(
+
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: Colors.white70,
+ width: 2
+ )
+ ),
+
+ width: 30,
+ height: 30,
+
+ alignment: Alignment.center,
+
+ child: Text(
+ "${((speed) * 2.237).toInt()}",
+ style: GoogleFonts.teko(
+ fontSize: 20,
+ color: Colors.white70,
+ height: 1
+ ),
+ )
+ ),
+
+ const SizedBox(
+ height: 4,
+ ),
+
+ Text(
+ "MPH",
+ style: GoogleFonts.teko(
+ fontSize: 20,
+ color: Colors.white70,
+ height: 1
+ ),
+ ),
+
+ ],
+
+ ),
+ ),
+
+ ],
+ ),
+
+ );
+ }
+}
+
+class AnnouncementPicker extends StatefulWidget {
final Color backgroundColor;
final Color outlineColor;
- final List announcements;
+ final List announcements;
- const ManualAnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements});
+ const AnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements});
@override
- State createState() => _ManualAnnouncementPickerState();
+ State createState() => _AnnouncementPickerState();
}
-class _ManualAnnouncementPickerState extends State {
+class _AnnouncementPickerState extends State {
List announcementWidgets = [];
@@ -255,13 +376,9 @@ class _ManualAnnouncementPickerState extends State {
}
int i = 0;
- for (NamedAnnouncementQueueEntry announcement in widget.announcements!) {
+ for (Widget announcement in widget.announcements!) {
announcementWidgets.add(
- _ManualAnnouncementEntry(
- announcement: announcement,
- index: i,
- outlineColor: Colors.white70
- )
+ announcement
);
i++;
}
@@ -436,7 +553,7 @@ class _ManualAnnouncementPickerState extends State {
Positioned.fill(
child: ElevatedButton(
onPressed: () {
- _currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length);
+ _currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
@@ -489,7 +606,7 @@ class _ManualAnnouncementPickerState extends State {
Positioned.fill(
child: ElevatedButton(
onPressed: () {
- _currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length);
+ _currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length, increment: 4);
setState(() {});
print(_currentIndex);
},
@@ -529,7 +646,7 @@ class _ManualAnnouncementPickerState extends State {
}
}
-class StopAnnouncementPicker extends ManualAnnouncementPicker {
+class StopAnnouncementPicker extends AnnouncementPicker {
final BusRouteVariant routeVariant;
StopAnnouncementPicker({
@@ -542,29 +659,52 @@ class StopAnnouncementPicker extends ManualAnnouncementPicker {
backgroundColor: backgroundColor,
outlineColor: outlineColor,
announcements: [
- for (BusRouteStops stop in routeVariant.busStops)
- ManualAnnouncementEntry(
- shortName: stop.formattedStopName,
- informationText: stop.formattedStopName,
- audioFileNames: [
- stop.getAudioFileName()
- ]
+ for (BusRouteStop stop in routeVariant.busStops)
+ _AnnouncementEntry(
+ label: stop.formattedStopName,
+ onPressed: () {
+ LiveInformation liveInformation = LiveInformation();
+ liveInformation.announcementModule.queueAnnounceByAudioName(
+ displayText: stop.formattedStopName,
+ audioNames: [stop.getAudioFileName()],
+ );
+ },
+ index: routeVariant.busStops.indexOf(stop),
+ outlineColor: outlineColor,
+ alert: LiveInformation().announcementModule.announcementCache[stop.getAudioFileName()] == null,
)
]
);
}
-int wrap(int i, int j, int length) {
- return ((i - j) % length + length) % length;
+int wrap(int i, int j, int length, {int increment = -1}) {
+ if (increment == -1) {
+ return ((i - j) % length + length) % length;
+ } else {
+ if (i >= length) {
+ return 0;
+ } else if (i < 0) {
+ double d = length / increment;
+ int n = d.toInt();
+
+ return (n-1) * increment;
+ } else {
+ return i;
+ }
+ }
}
-class _ManualAnnouncementEntry extends StatelessWidget {
+class _AnnouncementEntry extends StatelessWidget {
- final NamedAnnouncementQueueEntry announcement;
+ final String label;
+
+ final Function onPressed;
final int index;
final Color outlineColor;
- _ManualAnnouncementEntry({super.key, required this.announcement, required this.index, required this.outlineColor});
+ bool alert = false;
+
+ _AnnouncementEntry({super.key, required this.label, required this.onPressed, required this.index, required this.outlineColor, this.alert = false});
@override
Widget build(BuildContext context) {
@@ -591,35 +731,60 @@ class _ManualAnnouncementEntry extends StatelessWidget {
width: double.infinity,
- child: Transform.translate(
+ child: Row(
+ children: [
+ Row(
+ children: [
+ Container(
- offset: Offset(0, 4),
-
- child: Row(
- children: [
- Text(
- announcement.shortName,
- style: GoogleFonts.teko(
- fontSize: 25,
- color: outlineColor,
- )
- ),
- Expanded(
- child: Container(
-
- alignment: Alignment.centerRight,
+ constraints: const BoxConstraints(
+ maxWidth: 260
+ ),
child: Text(
- (index+1).toString(),
+ label,
style: GoogleFonts.teko(
fontSize: 25,
color: outlineColor,
- )
+ ),
+ overflow: TextOverflow.ellipsis,
),
),
- )
- ],
- ),
+
+ if (alert)
+ const SizedBox(
+ width: 4,
+ ),
+
+ if (alert)
+ Icon(
+ Icons.error,
+ color: Colors.red.shade800,
+ size: 25,
+ shadows: const [
+ Shadow(
+ color: Colors.black,
+ blurRadius: 2,
+ )
+ ],
+ )
+ ],
+ ),
+ Expanded(
+ child: Container(
+
+ alignment: Alignment.centerRight,
+
+ child: Text(
+ (index+1).toString(),
+ style: GoogleFonts.teko(
+ fontSize: 25,
+ color: outlineColor,
+ )
+ ),
+ ),
+ )
+ ],
)
),
@@ -627,8 +792,7 @@ class _ManualAnnouncementEntry extends StatelessWidget {
Positioned.fill(
child: ElevatedButton(
onPressed: () {
- LiveInformation liveInformation = LiveInformation();
- liveInformation.queueAnnouncement(announcement);
+ onPressed();
},
style: ElevatedButton.styleFrom(
diff --git a/lib/pages/routes.dart b/lib/pages/routes.dart
index 91cdfab..eb756da 100644
--- a/lib/pages/routes.dart
+++ b/lib/pages/routes.dart
@@ -1,5 +1,6 @@
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/pages/components/ibus_display.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -20,7 +21,19 @@ class _pages_RoutesState extends State {
LiveInformation liveInformation = LiveInformation();
List routes = [];
- routes.add(SizedBox(height: 10));
+ // routes.add(Container(
+ // width: double.infinity,
+ // height: 16,
+ // decoration: BoxDecoration(
+ // color: Colors.grey.shade900,
+ // border: const Border.symmetric(
+ // horizontal: BorderSide(
+ // color: Colors.white70,
+ // width: 2,
+ // ),
+ // )
+ // ),
+ // ));
for (BusRoute route in liveInformation.busSequences!.routes.values) {
if (!route.routeNumber.toLowerCase().contains(_controller.text.toLowerCase())) {
@@ -28,53 +41,81 @@ class _pages_RoutesState extends State {
}
routes.add(_Route(route, this));
- routes.add(SizedBox(height: 10));
+ routes.add(Container(
+ width: double.infinity,
+ height: 16,
+ decoration: BoxDecoration(
+ color: Colors.grey.shade900,
+ border: const Border.symmetric(
+ horizontal: BorderSide(
+ color: Colors.white70,
+ width: 2,
+ ),
+ )
+ ),
+ ));
+ }
+ if(!routes.isEmpty){
+ routes.removeLast();
}
return Container(
- color: Theme.of(context).colorScheme.background,
- width: double.infinity,
- // padding: const EdgeInsets.symmetric(horizontal: 10),
- child: Column(
- children: [
+ decoration: BoxDecoration(
+ color: Colors.grey.shade900,
+ ),
+ width: double.infinity,
+ child: Column(
- Container(
+ children: [
- padding: const EdgeInsets.all(10),
+ Container(
+ margin: const EdgeInsets.all(10),
-
- decoration: BoxDecoration(
- color: Theme.of(context).colorScheme.background,
- boxShadow: [
- BoxShadow(
- color: Colors.black.withOpacity(0.5),
- spreadRadius: 2,
- blurRadius: 4,
- ),
- ],
- ),
-
- child: TextField(
- controller: _controller,
- onChanged: (String value) {
- setState(() {});
- },
+ child: TextField(
+ controller: _controller,
+ decoration: InputDecoration(
+ hintText: ">",
),
+ onChanged: (String value) {
+ setState(() {});
+ },
),
+ ),
+ Container(
+ width: double.infinity,
+ height: 2,
+ color: Colors.white70,
+ ),
+
+ if (routes.isNotEmpty)
Expanded(
child: ListView(
children: routes,
),
- ),
+ )
+ else
+ Expanded(
+ child: Center(
+ child: Text(
+ "No routes found",
+ style: GoogleFonts.teko(
+ fontSize: 50,
+ fontWeight: FontWeight.bold,
+ color: Colors.white70,
+ height: 1
+ ),
+ ),
+ ),
+ )
- ],
+ ],
- )
+ )
);
}
@@ -93,28 +134,23 @@ class _Route extends StatelessWidget {
List Variants = [];
for (BusRouteVariant variant in route.routeVariants.values) {
- Variants.add(const SizedBox(height: 10));
Variants.add(_Variant(route, variant, tfL_Dataset_TestState));
+
+ if (route.routeVariants.values.last != variant) {
+ Variants.add(Container(
+ width: double.infinity,
+ height: 2,
+ color: Colors.white70,
+ ));
+ }
+
}
return Container(
alignment: Alignment.center,
- decoration: BoxDecoration(
- boxShadow: [
- BoxShadow(
- color: Colors.black.withOpacity(0.5),
- spreadRadius: 2,
- blurRadius: 4,
- ),
- ],
- color: Colors.grey.shade900,
- borderRadius: BorderRadius.circular(10),
- ),
-
- margin: const EdgeInsets.symmetric(horizontal: 10),
- padding: const EdgeInsets.all(10),
+ color: Colors.grey.shade900,
width: 100,
@@ -125,21 +161,27 @@ class _Route extends StatelessWidget {
children: [
+
+
Container(
decoration: BoxDecoration(
- color: Colors.grey.shade800,
- borderRadius: BorderRadius.circular(5),
+ color: Colors.transparent,
+ border: Border.all(
+ color: Colors.white70,
+ width: 2,
+ ),
),
padding: const EdgeInsets.all(8),
+ margin: const EdgeInsets.all(4),
child: Text(
"Route: ${route.routeNumber}",
- style: GoogleFonts.montserrat(
- fontSize: 20,
+ style: GoogleFonts.teko(
+ fontSize: 25,
fontWeight: FontWeight.bold,
- color: Colors.white,
+ color: Colors.white70,
height: 1
),
@@ -147,12 +189,35 @@ class _Route extends StatelessWidget {
),
- ListView(
- children: Variants,
- shrinkWrap: true,
- physics: const NeverScrollableScrollPhysics(),
+ Container(
+ width: double.infinity,
+ height: 2,
+ color: Colors.white70
+
),
+ Container(
+
+ decoration: BoxDecoration(
+ color: Colors.transparent,
+ border: Border.all(
+ color: Colors.white70,
+ width: 2,
+ ),
+ ),
+
+ margin: const EdgeInsets.all(4),
+
+ child: ListView(
+ children: Variants,
+ shrinkWrap: true,
+ physics: const NeverScrollableScrollPhysics(),
+ ),
+ ),
+
+
+
+
],
),
@@ -181,7 +246,7 @@ class _Variant extends StatelessWidget {
Container(
decoration: BoxDecoration(
- color: Colors.grey.shade800,
+ color: Colors.transparent,
borderRadius: BorderRadius.circular(5),
),
@@ -198,10 +263,10 @@ class _Variant extends StatelessWidget {
children: [
Text(
"Start:",
- style: GoogleFonts.montserrat(
- fontSize: 15,
+ style: GoogleFonts.teko(
+ fontSize: 20,
fontWeight: FontWeight.bold,
- color: Colors.white,
+ color: Colors.white70,
height: 1,
),
),
@@ -210,14 +275,14 @@ class _Variant extends StatelessWidget {
Expanded(
child: TextScroll(
- "${variant.busStops.first.formattedStopName}",
+ variant.busStops.first.formattedStopName,
mode: TextScrollMode.bouncing,
pauseBetween: const Duration(seconds: 2),
pauseOnBounce: const Duration(seconds: 2),
- style: GoogleFonts.montserrat(
- fontSize: 15,
+ style: GoogleFonts.teko(
+ fontSize: 20,
fontWeight: FontWeight.normal,
- color: Colors.white,
+ color: Colors.white70,
height: 1,
),
),
@@ -232,10 +297,11 @@ class _Variant extends StatelessWidget {
children: [
Text(
"End:",
- style: GoogleFonts.montserrat(
- fontSize: 15,
+ style: GoogleFonts.teko(
+ fontSize: 20,
fontWeight: FontWeight.bold,
- color: Colors.white,
+ color: Colors.white70,
+ height: 1,
),
),
@@ -247,10 +313,10 @@ class _Variant extends StatelessWidget {
mode: TextScrollMode.bouncing,
pauseBetween: const Duration(seconds: 2),
pauseOnBounce: const Duration(seconds: 2),
- style: GoogleFonts.montserrat(
- fontSize: 15,
+ style: GoogleFonts.teko(
+ fontSize: 20,
fontWeight: FontWeight.normal,
- color: Colors.white,
+ color: Colors.white70,
height: 1,
),
),
@@ -338,13 +404,12 @@ class _Variant extends StatelessWidget {
Navigator.of(context).pop();
LiveInformation liveInformation = LiveInformation();
- liveInformation.setRouteVariant(variant);
+ await liveInformation.setRouteVariant(variant);
- liveInformation.queueAnnouncement(
- await liveInformation.getDestinationAnnouncement(
- variant,
- sendToServer: true,
- )
+ liveInformation.announcementModule.queueAnnouncementByRouteVariant(
+ routeVariant: variant,
+ scheduledTime: liveInformation.syncedTimeModule.Now(),
+ sendToServer: false
);
tfL_Dataset_TestState.setState(() {});
diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart
index 3614015..24bd460 100644
--- a/lib/pages/settings.dart
+++ b/lib/pages/settings.dart
@@ -1,9 +1,12 @@
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/backend/modules/commands.dart';
+import 'package:bus_infotainment/utils/delegates.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
+import 'package:text_scroll/text_scroll.dart';
import 'package:url_launcher/url_launcher_string.dart';
class pages_Settings extends StatefulWidget {
@@ -14,22 +17,87 @@ class pages_Settings extends StatefulWidget {
class _pages_SettingsState extends State {
+ late final Widget _loginPage;
+
+ @override
+ void initState() {
+ // TODO: implement initState
+ super.initState();
+
+ if (!LiveInformation().auth.isAuthenticated()){
+ _loginPage = _LoginPage(
+ onLogin: () {
+ setState(() {});
+ },
+ );
+ } else {
+ _loginPage = Container(
+ padding: const EdgeInsets.all(8),
+ child: ElevatedButton(
+ onPressed: (){
+ setState(() {});
+ LiveInformation().auth.deleteSession();
+
+ },
+
+ // make the corner radius 4, background color match the theme, and text colour white, fill to width of parent
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Theme.of(context).colorScheme.primary,
+ foregroundColor: Colors.white,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(4)
+ ),
+ minimumSize: Size(double.infinity, 48)
+ ),
+
+ child: Text(
+ "Sign out",
+ style: GoogleFonts.interTight(
+ fontSize: 15,
+ fontWeight: FontWeight.w600,
+ color: Colors.white,
+ letterSpacing: 0.5
+ )
+ )
+ ),
+ );
+ }
+ }
+
@override
Widget build(BuildContext context) {
- if (LiveInformation().auth.isAuthenticated()){
- return Container(
+ return Container(
+ child: SingleChildScrollView(
+ child: Column(
+
+ children: [
+
+ Container(
+ margin: const EdgeInsets.all(8),
+ child: Console()
+ ),
+ Container(
+ height: 2,
+ width: double.infinity,
+ color: Colors.white70,
+ ),
- );
- } else {
- return _LoginPage(
- onLogin: () {
+ Container(
- },
- );
- }
+ padding: const EdgeInsets.all(8),
+
+ child: _loginPage,
+ )
+
+ ],
+
+ ),
+ )
+
+ );
}
}
@@ -626,4 +694,118 @@ class PW_TextField extends StatelessWidget {
);
}
+}
+
+// Console widget
+class Console extends StatefulWidget {
+
+ Console({super.key});
+
+ @override
+ State createState() => _ConsoleState();
+}
+
+class _ConsoleState extends State {
+
+ ListenerReceipt? _listenerReceipt;
+
+ @override
+ void initState() {
+ // TODO: implement initState
+ super.initState();
+
+ _listenerReceipt = LiveInformation().commandModule.onCommandReceived.addListener((p0) {
+ print("Command received, updating console");
+
+ setState(() {});
+ });
+
+ }
+
+ @override
+ void dispose() {
+ // TODO: implement dispose
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+
+ List commands = [];
+
+ TextEditingController commandController = TextEditingController();
+
+ commands.add(
+ Text("Command History:")
+ );
+
+ for (int i = 0; i < LiveInformation().commandModule.commandHistory.length; i++){
+ CommandInfo command = LiveInformation().commandModule.commandHistory[i];
+
+ commands.add(
+ TextScroll(
+ command.command,
+ style: GoogleFonts.teko(
+ fontSize: 15,
+ fontWeight: FontWeight.w400,
+ color: Colors.grey.shade300,
+ letterSpacing: 0.1,
+ ),
+ mode: TextScrollMode.bouncing,
+ pauseBetween: const Duration(seconds: 2),
+ pauseOnBounce: const Duration(seconds: 1),
+ )
+ );
+ }
+
+ return Container(
+
+ decoration: BoxDecoration(
+ border: Border.all(color: Colors.white70, width: 2),
+ color: Colors.black,
+ ),
+
+ child: Column(
+
+ children: [
+
+ Container(
+ padding: const EdgeInsets.all(8),
+
+ height: 300,
+
+ child: ListView(
+ children: commands,
+ ),
+ ),
+
+ Container(
+ height: 2,
+ width: double.infinity,
+ color: Colors.white70,
+ ),
+
+ Container(
+ height: 50,
+ padding: const EdgeInsets.all(8),
+ child: TextField(
+ controller: commandController,
+ decoration: const InputDecoration(
+ hintText: ">",
+ ),
+ style: GoogleFonts.teko(
+ height: 1,
+ ),
+ onSubmitted: (value) {
+ commandController.clear();
+ LiveInformation().commandModule.executeCommand(value);
+ },
+ ),
+ )
+
+ ],
+
+ ),
+ );
+ }
}
\ No newline at end of file
diff --git a/lib/pages/tfl_dataset_test.dart b/lib/pages/tfl_dataset_test.dart
index cf70193..b464716 100644
--- a/lib/pages/tfl_dataset_test.dart
+++ b/lib/pages/tfl_dataset_test.dart
@@ -5,11 +5,15 @@ import 'package:bus_infotainment/pages/display.dart';
import 'package:bus_infotainment/pages/home.dart';
import 'package:bus_infotainment/pages/routes.dart';
import 'package:bus_infotainment/pages/settings.dart';
-import 'package:bus_infotainment/singletons/live_information.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/tfl_datasets.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:text_scroll/text_scroll.dart';
+import 'package:window_manager/window_manager.dart';
+
+import 'components/ibus_display.dart';
class TfL_Dataset_Test extends StatefulWidget {
@@ -19,11 +23,13 @@ class TfL_Dataset_Test extends StatefulWidget {
class TfL_Dataset_TestState extends State {
- int _selectedIndex = 0;
+ int _selectedIndex = 1;
bool hideUI = false;
+ bool shouldCurve = false;
+ bool rotated = false;
- late final List Pages;
+ late final List Pages;
TfL_Dataset_TestState() {
Pages = [
@@ -42,111 +48,434 @@ class TfL_Dataset_TestState extends State {
_selectedIndex = min(_selectedIndex, Pages.length - 1);
_selectedIndex = max(_selectedIndex, 0);
+ hideUI = _selectedIndex == 2 ? hideUI : false;
+
+ // print the window size
+
+ if (defaultTargetPlatform == TargetPlatform.android) {
+ shouldCurve = true;
+ } else {
+ rotated = _selectedIndex == 2;
+
+ print("Window size: ${MediaQuery.of(context).size}");
+
+ windowManager.getSize().then((value) {
+ double aspectRatio = value.width / value.height;
+ double targetAspectRatio = rotated ? 850.3 / 411.4 : 411.4 / 850.3;
+
+ if ((aspectRatio - targetAspectRatio).abs() > 0.01) { // Add a tolerance value
+ if (aspectRatio != targetAspectRatio) {
+ windowManager.setSize(Size(value.height * targetAspectRatio, value.height));
+ }
+ }
+ });
+ }
+
+
return Scaffold(
- appBar: !hideUI ? AppBar(
+ // appBar: !hideUI ? AppBar(
+ //
+ // surfaceTintColor: Colors.transparent,
+ //
+ // title: Container(
+ //
+ // child: Column(
+ //
+ // crossAxisAlignment: CrossAxisAlignment.start,
+ //
+ // children: [
+ //
+ // Text(
+ // "Bus Infotainment",
+ // style: GoogleFonts.teko(
+ // fontSize: 25,
+ // fontWeight: FontWeight.bold,
+ // color: Colors.white,
+ // height: 1,
+ // ),
+ // ),
+ //
+ // Row(
+ //
+ // children: [
+ //
+ // Text(
+ // "Selected: ",
+ // style: GoogleFonts.teko(
+ // fontSize: 20,
+ // fontWeight: FontWeight.w600,
+ // color: Colors.white,
+ // height: 1,
+ // ),
+ // ),
+ //
+ // if (liveInformation.getRouteVariant() != null)
+ // Container(
+ //
+ // decoration: BoxDecoration(
+ // color: Colors.black,
+ // ),
+ //
+ // padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
+ //
+ // child: Text(
+ // "${liveInformation.getRouteVariant()!.busRoute.routeNumber} to ${liveInformation.getRouteVariant()!.busStops.last.formattedStopName}",
+ // style: GoogleFonts.montserrat(
+ // fontSize: 20,
+ // fontWeight: FontWeight.w500,
+ // color: Colors.orange.shade900,
+ // ),
+ // ),
+ //
+ // )
+ // else
+ // Text(
+ // "None",
+ // style: GoogleFonts.teko(
+ // fontSize: 20,
+ // fontWeight: FontWeight.w500,
+ // color: Colors.white,
+ // ),
+ // ),
+ // ],
+ //
+ // )
+ //
+ // ],
+ //
+ // ),
+ // ),
+ // ) : null,
+ body: Container(
- surfaceTintColor: Colors.transparent,
+ width: double.infinity,
+ height: double.infinity,
- title: Container(
+ child: RotatedBox(
+ quarterTurns: rotated ? 3 : 0,
+ child: FittedBox(
- child: Column(
+ alignment: Alignment.topCenter,
+ fit: BoxFit.fitWidth,
- crossAxisAlignment: CrossAxisAlignment.start,
+ child: Container(
- children: [
-
- Text(
- "Bus Infotainment",
- style: GoogleFonts.teko(
- fontSize: 25,
- fontWeight: FontWeight.bold,
- color: Colors.white,
- height: 1,
- ),
+ constraints: const BoxConstraints(
+ maxWidth: 411.4,
+ maxHeight: 850.3,
),
- Row(
+ child: Container(
- children: [
-
- Text(
- "Selected: ",
- style: GoogleFonts.teko(
- fontSize: 20,
- fontWeight: FontWeight.w600,
- color: Colors.white,
- height: 1,
- ),
+ decoration: BoxDecoration(
+ borderRadius: shouldCurve ? const BorderRadius.only(
+ bottomLeft: Radius.circular(15),
+ bottomRight: Radius.circular(15),
+ ) : null,
+ border: Border.all(
+ color: Colors.white70,
+ width: 2,
),
+ color: Colors.grey.shade900,
+ ),
- if (liveInformation.getRouteVariant() != null)
+ margin: const EdgeInsets.all(6),
+
+
+ child: Column(
+
+ children: [
+
+ if (!hideUI)
Container(
- decoration: BoxDecoration(
- color: Colors.black,
- ),
+ margin: const EdgeInsets.all(6),
- padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
+ child: ibus_display(),
+ ),
- child: Text(
- "${liveInformation.getRouteVariant()!.busRoute.routeNumber} to ${liveInformation.getRouteVariant()!.busStops.last.formattedStopName}",
- style: GoogleFonts.montserrat(
- fontSize: 20,
- fontWeight: FontWeight.w500,
- color: Colors.orange.shade900,
+ if (!hideUI)
+ Container(
+ width: double.infinity,
+ height: 2,
+ color: Colors.white70,
+ ),
+
+ Expanded(
+ child: Container(
+
+ margin: const EdgeInsets.all(8),
+
+ decoration: BoxDecoration(
+ border: Border.all(
+ color: Colors.white70,
+ width: 2,
+ ),
+ color: Colors.grey.shade900,
+ borderRadius: hideUI && shouldCurve ? const BorderRadius.only(
+ bottomLeft: Radius.circular(7),
+ bottomRight: Radius.circular(7),
+ ) : null,
),
- ),
- )
- else
- Text(
- "None",
- style: GoogleFonts.teko(
- fontSize: 20,
- fontWeight: FontWeight.w500,
- color: Colors.white,
+ child: ClipRRect(
+
+ // curved corners
+ borderRadius: BorderRadius.only(
+ bottomLeft: Radius.circular(7),
+ bottomRight: Radius.circular(7),
+ ),
+
+ child: Pages[_selectedIndex],
+ )
),
),
- ],
- )
+ if (!hideUI)
+ Container(
+ width: double.infinity,
+ height: 2,
+ color: Colors.white70,
+ ),
- ],
+ if (!hideUI)
+ Container(
+ height: 50,
+ child: Row(
+
+ children: [
+
+ Expanded(
+ child: Stack(
+ children: [
+ Container(
+ alignment: Alignment.center,
+ margin: const EdgeInsets.all(10),
+ child: Text(
+ "Home",
+ style: GoogleFonts.teko(
+ color: Colors.white70,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ )
+ ),
+ Positioned.fill(
+ child: ElevatedButton(
+ onPressed: () {
+ setState(() {
+ _selectedIndex = 0;
+ });
+ },
+
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.transparent,
+ shadowColor: Colors.transparent,
+ surfaceTintColor: Colors.transparent,
+ foregroundColor: Colors.transparent,
+
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+
+ ),
+
+ child: Container()
+ ),
+ )
+ ],
+ ),
+ ),
+
+ Container(
+ width: 2,
+ height: double.infinity,
+ color: Colors.white70,
+ ),
+
+ Expanded(
+ child: Stack(
+ children: [
+ Container(
+ alignment: Alignment.center,
+ margin: const EdgeInsets.all(10),
+ child: Text(
+ "Routes",
+ style: GoogleFonts.teko(
+ color: Colors.white70,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ )
+ ),
+ Positioned.fill(
+ child: ElevatedButton(
+ onPressed: () {
+ setState(() {
+ _selectedIndex = 1;
+ });
+ },
+
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.transparent,
+ shadowColor: Colors.transparent,
+ surfaceTintColor: Colors.transparent,
+ foregroundColor: Colors.transparent,
+
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+
+ ),
+
+ child: Container()
+ ),
+ )
+ ],
+ ),
+ ),
+
+ Container(
+ width: 2,
+ height: double.infinity,
+ color: Colors.white70,
+ ),
+
+ Expanded(
+ child: Stack(
+ children: [
+ Container(
+ alignment: Alignment.center,
+ margin: const EdgeInsets.all(10),
+ child: Text(
+ "Display",
+ style: GoogleFonts.teko(
+ color: Colors.white70,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ )
+ ),
+ Positioned.fill(
+ child: ElevatedButton(
+ onPressed: () {
+ setState(() {
+ _selectedIndex = 2;
+ });
+ },
+
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.transparent,
+ shadowColor: Colors.transparent,
+ surfaceTintColor: Colors.transparent,
+ foregroundColor: Colors.transparent,
+
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+
+ ),
+
+ child: Container()
+ ),
+ )
+ ],
+ ),
+ ),
+
+ Container(
+ width: 2,
+ height: double.infinity,
+ color: Colors.white70,
+ ),
+
+ Expanded(
+ child: Stack(
+ children: [
+ Container(
+ alignment: Alignment.center,
+ margin: const EdgeInsets.all(10),
+ child: Text(
+ "Settings",
+ style: GoogleFonts.teko(
+ color: Colors.white70,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ )
+ ),
+ Positioned.fill(
+ child: ElevatedButton(
+ onPressed: () {
+ setState(() {
+ _selectedIndex = 3;
+ });
+ },
+
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.transparent,
+ shadowColor: Colors.transparent,
+ surfaceTintColor: Colors.transparent,
+ foregroundColor: Colors.transparent,
+
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(0),
+ ),
+
+ ),
+
+ child: Container()
+ ),
+ )
+ ],
+ ),
+ ),
+
+
+ ],
+
+ ),
+ )
+
+ ],
+
+ )
+ ),
+ ),
),
),
- ) : null,
- body: Pages[_selectedIndex],
+ ),
- bottomNavigationBar: !hideUI ? NavigationBar(
- selectedIndex: _selectedIndex,
- destinations: const [
- NavigationDestination(
- icon: Icon(Icons.home),
- label: "Home",
- ),
- NavigationDestination(
- icon: Icon(Icons.bus_alert),
- label: "Routes",
- ),
- NavigationDestination(
- icon: Icon(Icons.tv),
- label: "Display",
- ),
- NavigationDestination(
- icon: Icon(Icons.settings),
- label: "Settings",
- ),
- ],
- onDestinationSelected: (int index) {
- setState(() {
- _selectedIndex = index;
- });
- },
-
- ) : null,
+ // bottomNavigationBar: !hideUI ? NavigationBar(
+ // selectedIndex: _selectedIndex,
+ // destinations: const [
+ // NavigationDestination(
+ // icon: Icon(Icons.home),
+ // label: "Home",
+ // ),
+ // NavigationDestination(
+ // icon: Icon(Icons.bus_alert),
+ // label: "Routes",
+ // ),
+ // NavigationDestination(
+ // icon: Icon(Icons.tv),
+ // label: "Display",
+ // ),
+ // NavigationDestination(
+ // icon: Icon(Icons.settings),
+ // label: "Settings",
+ // ),
+ // ],
+ // onDestinationSelected: (int index) {
+ // setState(() {
+ // _selectedIndex = index;
+ // });
+ // },
+ //
+ // ) : null,
);
}
}
diff --git a/lib/singletons/live_information.dart b/lib/singletons/live_information.dart
deleted file mode 100644
index ae23eaa..0000000
--- a/lib/singletons/live_information.dart
+++ /dev/null
@@ -1,855 +0,0 @@
-
-// Singleton
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:appwrite/appwrite.dart' as appwrite;
-import 'package:appwrite/models.dart' as models;
-import 'package:bus_infotainment/audio_cache.dart';
-import 'package:bus_infotainment/auth/api_constants.dart';
-import 'package:bus_infotainment/auth/auth_api.dart';
-import 'package:bus_infotainment/tfl_datasets.dart';
-import 'package:bus_infotainment/utils/audio%20wrapper.dart';
-import 'package:bus_infotainment/utils/delegates.dart';
-import 'package:flutter/foundation.dart';
-import 'package:flutter/services.dart';
-import 'package:http/http.dart' as http;
-import 'package:ntp/ntp.dart';
-
-class LiveInformation {
-
- static final LiveInformation _singleton = LiveInformation._internal();
-
- factory LiveInformation() {
- return _singleton;
- }
-
- LiveInformation._internal();
-
- Future Initialize() async {
-
- {
- // Load the bus sequences
-
- try {
-
- http.Response response = await http.get(Uri.parse('https://tfl.gov.uk/bus-sequences.csv'));
-
- busSequences = BusSequences.fromCSV(response.body);
-
- print("Loaded bus sequences from TFL");
-
- } catch (e) {
-
- String csv = await rootBundle.loadString("assets/datasets/bus-sequences.csv");
-
- busSequences = BusSequences.fromCSV(csv);
-
- print("Loaded bus sequences from assets");
- }
-
- if (auth.isAuthenticated()){
- print("Auth is authenticated");
- setupRealtime();
- } else {
- print("Auth is not authenticated");
- auth.onLogin.addListener((value) {
- setupRealtime();
- });
- }
-
- }
-
- refreshTimer();
- }
-
-
- Timer refreshTimer() => Timer.periodic(const Duration(milliseconds: 100), (timer) async {
- await updateNtpOffset();
- _handleAnnouncementQueue();
- });
-
-
- int ntpOffset = -1;
- DateTime lastNtpUpdate = DateTime.now().add(const Duration(seconds: -15));
- /// updates the NTP offset from DateTime.now()
- Future updateNtpOffset() async {
-
- // Only update the NTP offset every 10 seconds
- if (DateTime.now().difference(lastNtpUpdate).inSeconds < 10) {
- return;
- }
-
- var res = await http.get(Uri.parse('http://worldtimeapi.org/api/timezone/Europe/London'));
- if (res.statusCode == 200) {
- var json = jsonDecode(res.body);
- DateTime time = DateTime.parse(json['datetime']);
- ntpOffset = time.millisecondsSinceEpoch - DateTime.now().millisecondsSinceEpoch;
- lastNtpUpdate = DateTime.now();
-
- }
- }
-
- DateTime getNow() {
- if (ntpOffset == -1) {
- throw Exception("NTP offset not set");
- }
- return DateTime.now().add(Duration(milliseconds: ntpOffset));
- }
-
-
- AudioWrapper audioPlayer = AudioWrapper();
- AnnouncementCache announcementCache = AnnouncementCache();
- List announcementQueue = [];
- DateTime lastAnnouncementTimeStamp = DateTime.now().toUtc();
- EventDelegate announcementDelegate = EventDelegate();
- String _currentAnnouncement = "*** NO MESSAGE ***";
-
- String get currentAnnouncement => _currentAnnouncement;
- void set currentAnnouncement(String value) {
- _currentAnnouncement = value;
- }
-
- bool isPlayingAnnouncement = false;
- void _handleAnnouncementQueue() async {
-
- int timerInterval = 100;
-
- // print("Handling announcement queue");
- if (!isPlayingAnnouncement) {
- if (announcementQueue.isNotEmpty) {
-
- print("Handling announcement queue");
-
- AnnouncementQueueEntry announcement = announcementQueue.first;
-
- print("Queue length: ${announcementQueue.length}");
-
- {
- DateTime now = getNow();
- if (announcement.scheduledTime != null) {
- int milisecondDifference = abs(now.millisecondsSinceEpoch - announcement.scheduledTime!.millisecondsSinceEpoch);
- // print("Q Difference: ${milisecondDifference}");
- if (milisecondDifference <= timerInterval) {
- // Account for the time lost by the periodic timer
- announcementQueue.remove(announcement);
- await Future.delayed(Duration(milliseconds: timerInterval - milisecondDifference));
- } else {
- print("Due in: ${milisecondDifference}ms");
- return;
- }
- }
- }
-
- isPlayingAnnouncement = true;
-
- if (kIsWeb) {
- await Future.delayed(Duration(milliseconds: 100));
- }
-
-
- print("Displaying announcement: ${announcement.displayText}");
- announcementDelegate.trigger(announcement);
- _currentAnnouncement = announcement.displayText;
-
- lastAnnouncementTimeStamp = getNow();
-
- if (announcement.audioSources.isNotEmpty) {
- try {
- for (AudioWrapperSource source in announcement.audioSources) {
-
- Duration? duration = await audioPlayer.play(source);
- await Future.delayed(duration!);
- if (announcement.audioSources.last != source) {
- await Future.delayed(Duration(milliseconds: 500));
- }
- }
- audioPlayer.stop();
- } catch (e) {
-
- }
- } else {
- if (announcementQueue.isNotEmpty) {
- await Future.delayed(Duration(seconds: 5));
- }
- }
-
- if (announcementQueue.contains(announcement)) {
- announcementQueue.remove(announcement);
- }
-
- isPlayingAnnouncement = false;
- print("Popped announcement queue");
- print("Queue length after: ${announcementQueue.length}");
- }
- }
- }
-
- Future _getDestinationAnnouncement(BusRouteVariant routeVariant, {bool sendToServer = false}) async {
-
- String display = "${routeVariant.busRoute.routeNumber} to ${routeVariant.busStops.last.formattedStopName}";
-
- String audio_route = "R_${routeVariant.busRoute.routeNumber}_001.mp3";
- String audio_destination = routeVariant.busStops.last.getAudioFileName();
-
- // Cache the audio files
- await announcementCache.loadAnnouncements([audio_route, audio_destination]);
-
- AudioWrapperSource source_route = AudioWrapperByteSource(announcementCache[audio_route]);
- AudioWrapperSource source_destination = AudioWrapperByteSource(announcementCache[audio_destination]);
-
- return AnnouncementQueueEntry(
- sendToServer: sendToServer,
-
- displayText: display,
- audioSources: [source_route, AudioWrapperAssetSource("audio/to_destination.wav"), source_destination]
- );
-
- }
-
- Future getDestinationAnnouncement(BusRouteVariant routeVariant, {bool sendToServer = true}) async {
- return DestinationAnnouncementEntry(
- routeVariant: routeVariant,
- audioSources: [],
- sendToServer: sendToServer,
- );
- }
-
- late BusSequences busSequences;
- BusRouteVariant? _currentRouteVariant;
- EventDelegate routeVariantDelegate = EventDelegate();
-
- Future setRouteVariant(BusRouteVariant routeVariant) async {
- _currentRouteVariant = routeVariant;
- routeVariantDelegate.trigger(routeVariant);
-
- // cache all of the stop announcements
-
- List audioFiles = [];
-
- for (BusRouteStops stop in routeVariant.busStops) {
- audioFiles.add(stop.getAudioFileName());
- print("Cached stop audio: ${stop.getAudioFileName()}");
- }
-
- await announcementCache.loadAnnouncements(audioFiles);
-
-
- }
-
- BusRouteVariant? getRouteVariant() {
- return _currentRouteVariant;
- }
-
- void queueAnnouncement(AnnouncementQueueEntry announcement) async {
-
-
- // Make sure the timestamp of the announcement is after the last announcement
- // If so, dont queue it
- // If timestamp is null, then skip this check
- if (announcement.timestamp != null && announcement.timestamp!.toUtc().isBefore(lastAnnouncementTimeStamp)) {
- print("Announcement is too old");
-
- print("LastAnnouncement: $lastAnnouncementTimeStamp");
- print("Announcement: ${announcement.timestamp}");
-
- int difference = announcement.timestamp!.difference(lastAnnouncementTimeStamp).inMilliseconds;
- print("Difference: $difference");
- return;
- } else if (announcement.timestamp == null) {
- print("Announcement `${announcement.displayText}` does not have timestamp");
- }
-
-
-
- // If there is an announcement in the queue with the same timestamp, dont queue it
- if (announcementQueue.any((element) => element.timestamp == announcement.timestamp)) {
- print("Announcement with same timestamp already in queue");
- return;
- }
-
- if (!announcement.sendToServer) {
-
- if (announcement is DestinationAnnouncementEntry) {
-
- BusRouteVariant routeVariant = announcement.routeVariant;
-
- if (getRouteVariant() != routeVariant) {
- setRouteVariant(routeVariant);
- }
-
- announcementQueue.add(
- await _getDestinationAnnouncement(
- routeVariant,
- sendToServer: false
- )
- );
-
- print("Queued destination announcement: ${announcement.displayText}");
- print("Audios: ${announcement.audioSources.length}");
- return;
-
- } else if (announcement is ManualAnnouncementEntry) {
-
- List audioSources = [];
-
- for (String filename in announcement.audioFileNames) {
- audioSources.add(AudioWrapperByteSource(announcementCache[filename]));
- }
-
- announcementQueue.add(
- ManualAnnouncementEntry(
- shortName: announcement.shortName,
- informationText: announcement.displayText,
- audioFileNames: announcement.audioFileNames,
- audioSources: audioSources,
- sendToServer: false,
- )
- );
-
- print("Queued manual announcement: ${announcement.displayText} (no server)");
- return;
- }
-
- announcementQueue.add(announcement);
- print("Queued announcement: ${announcement.displayText} (no server)");
- return;
- }
-
- final databases = appwrite.Databases(auth.client);
-
- print("Queuing announcement: ${announcement.displayText} (server)");
- print("Announcement type: ${announcement.runtimeType}");
-
- if (announcement.runtimeType == InformationAnnouncementEntry) {
- announcement as InformationAnnouncementEntry;
- print("Queing to InformationAnnouncementEntry");
-
- // 5 sedonds in the future
- DateTime scheduledTime = (await getNow()).add(Duration(seconds: 1));
-
-
- final document = databases.createDocument(
- documentId: appwrite.ID.unique(),
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.INFORMATION_Q_COLLECTION_ID,
- data: {
- "ManualAnnouncementIndex": manualAnnouncements.indexOf(announcement),
- "ScheduledTime": scheduledTime.toIso8601String(),
- "SessionID": sessionID,
- }
- );
-
- print("Queued manual announcement: ${announcement.shortName} (server)");
-
- } else if (announcement.runtimeType == ManualAnnouncementEntry) {
- announcement as ManualAnnouncementEntry;
- print("Queing to ManualAnnouncementEntry");
-
- // 5 sedonds in the future
- DateTime scheduledTime = (await getNow()).add(Duration(seconds: 1));
-
- final document = databases.createDocument(
- documentId: appwrite.ID.unique(),
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.MANUAL_Q_COLLECTION_ID,
- data: {
- "DisplayText": announcement.displayText,
- "AudioFileNames": announcement.audioFileNames,
-
- "ScheduledTime": scheduledTime.toIso8601String(),
- "SessionID": sessionID,
- }
- );
-
- print("Queued manual announcement: ${announcement.shortName}");
-
- } else if (announcement.runtimeType == DestinationAnnouncementEntry) {
- announcement as DestinationAnnouncementEntry;
- print("Queing to DestinationAnnouncementEntry");
-
- // 5 sedonds in the future
- DateTime scheduledTime = (getNow()).add(Duration(seconds: 2));
-
- final document = databases.createDocument(
- documentId: appwrite.ID.unique(),
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.DEST_Q_COLLECTION_ID,
- data: {
- "RouteNumber": announcement.routeVariant.busRoute.routeNumber,
- "RouteVariantIndex": announcement.routeVariant.routeVariant,
-
- "ScheduledTime": scheduledTime.toIso8601String(),
- "SessionID": sessionID,
- }
- );
-
- print("Queued manual announcement: ${announcement.shortName} (server)");
-
- }
-
- }
-
- List manualAnnouncements = [
- InformationAnnouncementEntry(
- shortName: "Driver Change",
- informationText: "Driver Change",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/driverchange.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "No Standing Upr Deck",
- informationText: "No standing on the upper deck",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nostanding.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Face Covering",
- informationText: "Please wear a face covering!",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/facecovering.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Seats Upstairs",
- informationText: "Seats are available upstairs",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/seatsupstairs.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Bus Terminates Here",
- informationText: "Bus terminates here. Please take your belongings with you",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busterminateshere.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Bus On Diversion",
- informationText: "Bus on diversion. Please listen for further announcements",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busondiversion.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Destination Change",
- informationText: "Destination Changed - please listen for further instructions",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/destinationchange.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Wheelchair Space",
- informationText: "Wheelchair space requested",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace1.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Move Down The Bus",
- informationText: "Please move down the bus",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/movedownthebus.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Next Stop Closed",
- informationText: "The next bus stop is closed",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nextstopclosed.wav")],
- ),
- InformationAnnouncementEntry(
- shortName: "CCTV In Operation",
- informationText: "CCTV is in operation on this bus",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/cctvoperation.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Safe Door Opening",
- informationText: "Driver will open the doors when it is safe to do so",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/safedooropening.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Buggy Safety",
- informationText: "For your child's safety, please remain with your buggy",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/buggysafety.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Wheelchair Space 2",
- informationText: "Wheelchair priority space required",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace2.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Service Regulation",
- informationText: "Regulating service - please listen for further information",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/serviceregulation.mp3")],
- ),
- InformationAnnouncementEntry(
- shortName: "Bus Ready To Depart",
- informationText: "This bus is ready to depart",
- audioSources: [AudioWrapperAssetSource("audio/manual_announcements/readytodepart.mp3")],
- ),
- ];
-
- AuthAPI auth = AuthAPI();
- String sessionID = "65de648aa7f44684ecce";
- void updateServer() async {
-
-
-
- final databases = appwrite.Databases(auth.client);
-
- // final document = databases.updateDocument(
- // databaseId: ApiConstants.INFO_DATABASE_ID,
- // collectionId: ApiConstants.INFO_COLLECTION_ID,
- // documentId: documentID,
- // data: {
- // "Display": _currentAnnouncement,
- // }
- // );
-
- print("Updated server with announcement: $_currentAnnouncement");
-
- }
- void pullServer() async {
-
- if (auth.status == AuthStatus.UNAUTHENTICATED) {
- return;
- }
-
- final databases = appwrite.Databases(auth.client);
-
- // final document = await databases.getDocument(
- // databaseId: ApiConstants.INFO_DATABASE_ID,
- // collectionId: ApiConstants.INFO_COLLECTION_ID,
- // documentId: documentID,
- // );
-
- // queueAnnouncement(AnnouncementQueueEntry(
- // displayText: document.data['Display'],
- // audioSources: [],
- // sendToServer: false, // Don't send this back to the server, else we'll get an infinite loop
- // ));
-
- // print("Pulled announcement from server: ${document.data['Display']}");
- }
-
- bool purgeRunning = false;
- Future deleteAllManualQueueEntries() async {
-
- if (purgeRunning) {
- return;
- }
- purgeRunning = true;
-
- final databases = appwrite.Databases(auth.client);
- int offset = 0;
- const int limit = 25; // Maximum number of documents that can be fetched at once
-
- while (true) {
- // Fetch a page of documents from the manual queue collection
- print("Deleting manual queue entries");
- final manual_q = await databases.listDocuments(
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.MANUAL_Q_COLLECTION_ID,
- queries: [
- appwrite.Query.search("SessionID", sessionID),
- appwrite.Query.limit(limit),
- appwrite.Query.offset(offset),
- appwrite.Query.orderDesc('\$createdAt')
- ]
- );
-
- // If there are no documents in the fetched page, break the loop
- if (manual_q.documents.isEmpty) {
- break;
- }
-
- // Delete each document in the fetched page
- for (models.Document doc in manual_q.documents) {
- await databases.deleteDocument(
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.MANUAL_Q_COLLECTION_ID,
- documentId: doc.$id,
- );
- }
-
- // Go to the next page
- offset += limit;
- }
-
- print("Deleted all manual queue entries");
- }
-
- void pullQueue() async {
-
- if (auth.status == AuthStatus.UNAUTHENTICATED) {
- return;
- }
-
- List queue = [];
-
- final databases = appwrite.Databases(auth.client);
-
- // Pull the information queue
- {
- final manual_q = await databases.listDocuments(
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.INFORMATION_Q_COLLECTION_ID,
- queries: [
- appwrite.Query.search("SessionID", sessionID),
- appwrite.Query.limit(25),
- appwrite.Query.offset(0),
- appwrite.Query.orderDesc('\$createdAt')
- ]
- );
-
- for (models.Document doc in manual_q.documents) {
- int index = doc.data['ManualAnnouncementIndex'];
-
- InformationAnnouncementEntry announcement_clone =
- InformationAnnouncementEntry(
- shortName: manualAnnouncements[index].shortName,
- informationText: manualAnnouncements[index].displayText,
- audioSources: manualAnnouncements[index].audioSources,
- scheduledTime: doc.data["ScheduledTime"] != null
- ? DateTime.parse(doc.data["ScheduledTime"])
- : null,
- timestamp: DateTime.parse(doc.$createdAt),
- sendToServer: false,
- );
-
- // sort the queue by timestamp, so the oldest announcements are at the front
-
- queue.add(announcement_clone);
- }
- }
-
- // pull the destination queue
- {
- final dest_q = await databases.listDocuments(
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.DEST_Q_COLLECTION_ID,
- queries: [
- appwrite.Query.search("SessionID", sessionID),
- appwrite.Query.limit(25),
- appwrite.Query.offset(0),
- appwrite.Query.orderDesc('\$createdAt')
- ]
- );
-
- for (models.Document doc in dest_q.documents) {
-
- BusRoute? route = busSequences.routes[doc.data["RouteNumber"]];
-
- BusRouteVariant? routeVariant = route!.routeVariants[doc.data["RouteVariantIndex"]];
-
-
- DestinationAnnouncementEntry announcement_clone =
- DestinationAnnouncementEntry(
- routeVariant: routeVariant!,
- scheduledTime: doc.data["ScheduledTime"] != null
- ? DateTime.parse(doc.data["ScheduledTime"])
- : null,
- timestamp: DateTime.parse(doc.$createdAt),
- sendToServer: false,
- audioSources: [],
- );
-
- // sort the queue by timestamp, so the oldest announcements are at the front
-
- queue.add(announcement_clone);
- }
- }
-
- // Pull the manual queue
- {
- final manual_q = await databases.listDocuments(
- databaseId: ApiConstants.INFO_Q_DATABASE_ID,
- collectionId: ApiConstants.MANUAL_Q_COLLECTION_ID,
- queries: [
- appwrite.Query.search("SessionID", sessionID),
- appwrite.Query.limit(25),
- appwrite.Query.offset(0),
- appwrite.Query.orderDesc('\$createdAt')
- ]
- );
-
- for (models.Document doc in manual_q.documents) {
-
-
-
- List audioFileNames = doc.data["AudioFileNames"].cast();
-
- ManualAnnouncementEntry announcement_clone =
- ManualAnnouncementEntry(
- sendToServer: false,
-
- shortName: "",
- informationText: doc.data["DisplayText"],
- audioFileNames: audioFileNames,
-
- scheduledTime: doc.data["ScheduledTime"] != null
- ? DateTime.parse(doc.data["ScheduledTime"])
- : null,
-
- );
-
- // sort the queue by timestamp, so the oldest announcements are at the front
-
- queue.add(announcement_clone);
- }
- }
-
- for (AnnouncementQueueEntry entry in queue) {
-
- // Dont queue announcements that are older than now
- if (entry.scheduledTime != null && entry.scheduledTime!.isBefore(await getNow())) {
- continue;
- }
-
- queueAnnouncement(entry);
- }
-
- }
-
-
-
- appwrite.RealtimeSubscription? information_q_subscription;
- appwrite.RealtimeSubscription? manual_q_subscription;
- appwrite.RealtimeSubscription? destination_q_subscription;
-
- Future setupRealtime() async {
-
- if (information_q_subscription != null) {
- return;
- }
-
- // await deleteAllManualQueueEntries(); //todo
-
- print("Setting up realtime");
-
- // Websocket
- appwrite.Realtime realtime = appwrite.Realtime(auth.client);
-
- information_q_subscription = realtime.subscribe(
- ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.INFORMATION_Q_COLLECTION_ID}.documents'],
- );
- information_q_subscription?.stream.listen((event) {
- print("Manual queue entry added");
-
- pullQueue();
- });
-
- manual_q_subscription = realtime.subscribe(
- ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.MANUAL_Q_COLLECTION_ID}.documents'],
- );
- manual_q_subscription?.stream.listen((event) {
- print("Manual queue entry added");
-
- pullQueue();
- });
-
- destination_q_subscription = realtime.subscribe(
- ['databases.${ApiConstants.INFO_Q_DATABASE_ID}.collections.${ApiConstants.DEST_Q_COLLECTION_ID}.documents'],
- );
- destination_q_subscription?.stream.listen((event) {
- print("Destination queue entry added");
-
- pullQueue();
- });
-
- print("Subscribed to servers");
-
- await Future.delayed(Duration(seconds: 90));
-
- information_q_subscription?.close();
- information_q_subscription = null;
- manual_q_subscription?.close();
- manual_q_subscription = null;
- destination_q_subscription?.close();
- destination_q_subscription = null;
- print("Restarting realtime");
- setupRealtime();
-
- }
-
-
-
-}
-
-class AnnouncementQueueEntry {
- final String displayText;
- final List audioSources;
- bool sendToServer = true;
- DateTime? scheduledTime;
- DateTime? timestamp;
-
- AnnouncementQueueEntry({required this.displayText, required this.audioSources, this.sendToServer = true, this.scheduledTime, this.timestamp});
-}
-
-class NamedAnnouncementQueueEntry extends AnnouncementQueueEntry {
- final String shortName;
-
- NamedAnnouncementQueueEntry({
- required this.shortName,
- required String displayText,
- required List audioSources,
- DateTime? scheduledTime,
- DateTime? timestamp,
- bool sendToServer = true,
- }) : super(
- displayText: displayText,
- audioSources: audioSources,
- sendToServer: sendToServer,
- scheduledTime: scheduledTime,
- timestamp: timestamp,
- );
-}
-
-class ManualAnnouncementEntry extends NamedAnnouncementQueueEntry {
-
- final List audioFileNames;
-
- ManualAnnouncementEntry({
- required String shortName,
- required String informationText,
- required this.audioFileNames,
- List audioSources = const [],
- DateTime? scheduledTime,
- DateTime? timestamp,
- bool sendToServer = true,
- }) : super(
- shortName: shortName,
- displayText: informationText,
- audioSources: audioSources,
- sendToServer: sendToServer,
- scheduledTime: scheduledTime,
- timestamp: timestamp,
- );
-}
-
-class InformationAnnouncementEntry extends NamedAnnouncementQueueEntry {
-
-
- InformationAnnouncementEntry({
- required String shortName,
- required String informationText,
- required List audioSources,
- DateTime? scheduledTime,
- DateTime? timestamp,
- bool sendToServer = true,
- }) : super(
- shortName: shortName,
- displayText: informationText,
- audioSources: audioSources,
- sendToServer: sendToServer,
- scheduledTime: scheduledTime,
- timestamp: timestamp,
- );
-}
-
-class DestinationAnnouncementEntry extends NamedAnnouncementQueueEntry {
-
- final BusRouteVariant routeVariant;
-
- DestinationAnnouncementEntry({
- required this.routeVariant,
- required List audioSources,
- DateTime? scheduledTime,
- DateTime? timestamp,
- bool sendToServer = true,
- }) : super(
- shortName: "Destination",
- displayText: "${routeVariant.busRoute.routeNumber} to ${routeVariant.busStops.last.formattedStopName}",
- audioSources: audioSources,
- sendToServer: sendToServer,
- scheduledTime: scheduledTime,
- timestamp: timestamp,
- );
-
-}
-
-var abs = (int value) => value < 0 ? -value : value;
\ No newline at end of file
diff --git a/lib/tfl_datasets.dart b/lib/tfl_datasets.dart
index 7ca6c0b..cacf7ac 100644
--- a/lib/tfl_datasets.dart
+++ b/lib/tfl_datasets.dart
@@ -3,24 +3,64 @@
import 'dart:typed_data';
import 'package:bus_infotainment/audio_cache.dart';
+import 'package:bus_infotainment/backend/live_information.dart';
+import 'package:bus_infotainment/backend/modules/info_module.dart';
import 'package:bus_infotainment/utils/NameBeautify.dart';
+import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:csv/csv.dart';
+import 'package:vector_math/vector_math.dart';
-class BusSequences {
+class BusSequences extends InfoModule {
Map routes = {};
- BusSequences.fromCSV(String csv) {
+ Map destinations = {};
- List> rowsAsListOfValues = const CsvToListConverter().convert(csv);
+ BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) {
- rowsAsListOfValues.removeAt(0);
-
- for (int i = 0; i < rowsAsListOfValues.length; i++) {
+ // Init the bus destinations
+ List> destinationRows = const CsvToListConverter().convert(destinationsCSV);
+ destinationRows.removeAt(0);
+ for (int i = 0; i < destinationRows.length; i++) {
try {
- List entries = rowsAsListOfValues[i];
+ List entries = destinationRows[i];
+
+ String routeNumber = entries[0].toString();
+
+ BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
+
+ String blind = entries[1].toString();
+
+ double lat = double.parse(entries[2].toString());
+ double long = double.parse(entries[3].toString());
+
+ Vector2 grid = OSGrid.toNorthingEasting(lat, long);
+
+ BusDestination destination = BusDestination();
+ destination.destination = blind;
+ destination.easting = grid.x;
+ destination.northing = grid.y;
+
+ route.destinations.add(destination);
+
+ routes[routeNumber] = route;
+ destinations[blind] = destination;
+ } catch (e) {}
+ }
+
+ // Init the bus routes
+
+ List> busSequenceRows = const CsvToListConverter().convert(busSequencesCSV);
+ busSequenceRows.removeAt(0);
+
+ for (int i = 0; i < busSequenceRows.length; i++) {
+
+ try
+ {
+
+ List entries = busSequenceRows[i];
String routeNumber = entries[0].toString();
@@ -28,25 +68,28 @@ class BusSequences {
int routeVariant = entries[1];
- BusRouteVariant variant = route.routeVariants.containsKey(routeVariant) ? route.routeVariants[routeVariant]! : BusRouteVariant(routeVariant: routeVariant, busRoute: route);
-
- BusRouteStops stop = BusRouteStops();
+ BusRouteStop stop = BusRouteStop();
stop.stopName = entries[6].toString();
stop.stopCode = entries[4].toString();
stop.easting = entries[7];
stop.northing = entries[8];
+ stop.heading = entries[9] != "" ? entries[9] : -1;
+
+ BusRouteVariant variant = route.routeVariants.containsKey(routeVariant) ? route.routeVariants[routeVariant]! : BusRouteVariant(routeVariant: routeVariant, busRoute: route);
variant.busStops.add(stop);
+
route.routeVariants[routeVariant] = variant;
routes[routeNumber] = route;
- } catch (e) {
- // print("Error parsing bus sequence: $e");
}
-
+ catch (e) {
+ print("Error parsing bus sequence: $e");
+ }
}
+
}
}
@@ -55,6 +98,8 @@ class BusRoute {
String routeNumber = "";
+ List destinations = [];
+
AnnouncementCache? announcementCache;
Map routeVariants = {};
@@ -70,7 +115,7 @@ class BusRouteVariant {
int routeVariant = -1;
- List busStops = [];
+ List busStops = [];
late BusRoute busRoute;
@@ -78,14 +123,66 @@ class BusRouteVariant {
this.routeVariant = -1,
required this.busRoute,
});
+
+ BusDestination? _destination;
+ BusDestination? get destination {
+ if (_destination == null) {
+
+ // Get the nearest destination
+ BusDestination? nearestDestinationA;
+ double nearestDistanceA = double.infinity;
+
+ Vector2 stopLocation = Vector2(busStops.last.northing.toDouble(), busStops.last.easting.toDouble());
+
+ for (BusDestination destination in busRoute.destinations) {
+
+ Vector2 destinationLocation = Vector2(destination.northing.toDouble(), destination.easting.toDouble());
+
+ double distance = stopLocation.distanceTo(destinationLocation);
+
+ if (distance < nearestDistanceA) {
+ nearestDestinationA = destination;
+ nearestDistanceA = distance;
+ }
+
+ }
+
+ // get the nearest destination from global pool of destinations
+ BusDestination? nearestDestinationB;
+ double nearestDistanceB = double.infinity;
+
+ for (BusDestination destination in LiveInformation().busSequences.destinations.values) {
+
+ Vector2 destinationLocation = Vector2(destination.northing.toDouble(), destination.easting.toDouble());
+
+ double distance = stopLocation.distanceTo(destinationLocation);
+
+ if (distance < nearestDistanceB) {
+ nearestDestinationB = destination;
+ nearestDistanceB = distance;
+ }
+
+ }
+
+ // Choose the nearest destination
+ if (nearestDistanceA < nearestDistanceB) {
+ _destination = nearestDestinationA;
+ } else {
+ _destination = nearestDestinationB;
+ }
+
+ }
+ return _destination;
+ }
}
-class BusRouteStops {
+class BusRouteStop {
String stopName = "";
int easting = -1;
int northing = -1;
+ int heading = -1;
String stopCode = "";
@@ -122,4 +219,60 @@ class BusRouteStops {
}
+}
+
+class BusDestination {
+
+ String destination = "";
+
+ double easting = -1;
+ double northing = -1;
+
+ Future getAudioBytes() async {
+
+ // Convert the stop name to all caps
+ String name = destination.toUpperCase();
+
+ name = NameBeautify.beautifyStopName(name);
+
+ // replace & with N
+ name = name.replaceAll('&', 'N');
+
+ name = name.replaceAll('/', '');
+
+ name = name.replaceAll('\'', '');
+
+ name = name.replaceAll(' ', ' ');
+
+ // Replace space with underscore
+ name = name.replaceAll(' ', '_');
+
+ // convert to all caps
+ name = name.toUpperCase();
+
+ String audioNameA = "D_${name}_001.mp3";
+ String audioNameB = "S_${name}_001.mp3";
+ String audioNameC = "A_${name}_001.mp3";
+
+ print("Audio name A: $audioNameA");
+ print("Audio name B: $audioNameB");
+ print("Audio name C: $audioNameC");
+
+ await LiveInformation().announcementModule.announcementCache.loadAnnouncements([audioNameA, audioNameB, audioNameC]);
+
+ Uint8List? audioBytesA = LiveInformation().announcementModule.announcementCache[audioNameA];
+ Uint8List? audioBytesB = LiveInformation().announcementModule.announcementCache[audioNameB];
+ Uint8List? audioBytesC = LiveInformation().announcementModule.announcementCache[audioNameC];
+
+ if (audioBytesA != null) return audioBytesA;
+ if (audioBytesB != null) return audioBytesB;
+ if (audioBytesC != null) return audioBytesC;
+
+ print("No audio bytes found for $name");
+
+ return Uint8List(0);
+
+ }
+
+
}
\ No newline at end of file
diff --git a/lib/utils/OrdinanceSurveyUtils.dart b/lib/utils/OrdinanceSurveyUtils.dart
new file mode 100644
index 0000000..23145c9
--- /dev/null
+++ b/lib/utils/OrdinanceSurveyUtils.dart
@@ -0,0 +1,35 @@
+import 'dart:math' as math;
+import 'package:proj4dart/proj4dart.dart' as proj4;
+import 'package:vector_math/vector_math.dart';
+
+
+class OSGrid {
+
+ static List toLatLong(double northing, double easting) {
+
+ final sourceProjection = proj4.Projection.parse('+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 '
+ '+x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs'); // British National Grid
+ final destinationProjection = proj4.Projection.WGS84;// WGS84
+
+ final point = proj4.Point(x: easting, y: northing);
+ final transformedPoint = sourceProjection.transform(destinationProjection, point);
+
+
+
+ return [transformedPoint.y, transformedPoint.x];
+ }
+
+ static Vector2 toNorthingEasting(double latitude, double longitude) {
+
+ final sourceProjection = proj4.Projection.WGS84;// WGS84
+ final destinationProjection = proj4.Projection.parse('+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 '
+ '+x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs'); // British National Grid
+
+ final point = proj4.Point(x: longitude, y: latitude);
+ final transformedPoint = sourceProjection.transform(destinationProjection, point);
+
+ return Vector2(transformedPoint.x, transformedPoint.y);
+ }
+
+}
+
diff --git a/lib/utils/audio wrapper.dart b/lib/utils/audio wrapper.dart
index 8b6d3f7..e4c0699 100644
--- a/lib/utils/audio wrapper.dart
+++ b/lib/utils/audio wrapper.dart
@@ -3,6 +3,11 @@ import 'package:audioplayers/audioplayers.dart' as audioplayers;
import 'package:flutter/foundation.dart';
import 'package:just_audio/just_audio.dart' as justaudio;
+enum AudioWrapper_Mode {
+ Web,
+ Mobile
+}
+
enum AudioWrapper_State {
Playing,
NotPlaying
@@ -13,6 +18,16 @@ class AudioWrapper {
audioplayers.AudioPlayer _audioPlayer_AudioPlayer = audioplayers.AudioPlayer();
justaudio.AudioPlayer _justAudio_AudioPlayer = justaudio.AudioPlayer();
+ AudioWrapper_Mode mode = kIsWeb ? AudioWrapper_Mode.Web : AudioWrapper_Mode.Mobile;
+
+ AudioWrapper() {
+ // mode = AudioWrapper_Mode.Web;
+
+ print("AudioWrapper mode: $mode");
+
+ // mode = AudioWrapper_Mode.Mobile;
+ }
+
justaudio.AudioSource _convertSource_JustAudio(AudioWrapperSource source){
if (source is AudioWrapperByteSource){
return _ByteSource(source.bytes);
@@ -33,45 +48,94 @@ class AudioWrapper {
}
}
- Future play(AudioWrapperSource source) async {
- Duration? duration;
-
- if (kIsWeb) {
+ Future loadSource(AudioWrapperSource source) async {
+ if (mode == AudioWrapper_Mode.Web) {
// Use just_audio
justaudio.AudioSource audioSource = _convertSource_JustAudio(source);
- duration = await _justAudio_AudioPlayer.setAudioSource(audioSource);
+ await _justAudio_AudioPlayer.setAudioSource(audioSource);
- _justAudio_AudioPlayer.play();
-
-
- } else {
+ } else if (mode == AudioWrapper_Mode.Mobile) {
// Use audioplayers
audioplayers.Source audioSource = _convertSource_AudioPlayers(source);
- await _audioPlayer_AudioPlayer.play(audioSource);
+ await _audioPlayer_AudioPlayer.setSource(audioSource);
+ // await _audioPlayer_AudioPlayer.play(audioSource);
+ }
+ }
+ Future getDuration() async {
+ if (mode == AudioWrapper_Mode.Web) {
+ return _justAudio_AudioPlayer.duration;
+ } else if (mode == AudioWrapper_Mode.Mobile) {
+ return await _audioPlayer_AudioPlayer.getDuration();
+ }
+ }
+
+ Future play() async {
+
+ Duration? duration;
+
+ if (mode == AudioWrapper_Mode.Web) {
+ _justAudio_AudioPlayer.play();
+ duration = _justAudio_AudioPlayer.duration;
+ } else if (mode == AudioWrapper_Mode.Mobile) {
+ _audioPlayer_AudioPlayer.resume();
duration = await _audioPlayer_AudioPlayer.getDuration();
}
-
-
-
return duration;
}
+ // Future play(AudioWrapperSource source) async {
+ //
+ // Duration? duration;
+ //
+ // if (mode == AudioWrapper_Mode.Web) {
+ // // Use just_audio
+ //
+ // justaudio.AudioSource audioSource = _convertSource_JustAudio(source);
+ //
+ // duration = await _justAudio_AudioPlayer.setAudioSource(audioSource);
+ //
+ // _justAudio_AudioPlayer.play();
+ //
+ //
+ // } else if (mode == AudioWrapper_Mode.Mobile) {
+ // // Use audioplayers
+ //
+ // audioplayers.Source audioSource = _convertSource_AudioPlayers(source);
+ //
+ // await _audioPlayer_AudioPlayer.play(audioSource);
+ //
+ // duration = await _audioPlayer_AudioPlayer.getDuration();
+ // }
+ //
+ //
+ //
+ // return duration;
+ // }
+
void stop(){
- if (kIsWeb) {
+ if (mode == AudioWrapper_Mode.Web) {
_justAudio_AudioPlayer.stop();
- } else {
+ try {
+ _justAudio_AudioPlayer.dispose();
+ } catch (e) {}
+ _justAudio_AudioPlayer = justaudio.AudioPlayer();
+ } else if (mode == AudioWrapper_Mode.Mobile) {
_audioPlayer_AudioPlayer.stop();
+ try {
+ _audioPlayer_AudioPlayer.dispose();
+ } catch (e) {}
+ _audioPlayer_AudioPlayer = audioplayers.AudioPlayer();
}
}
AudioWrapper_State get state {
- if (kIsWeb) {
+ if (mode == AudioWrapper_Mode.Web) {
if (_justAudio_AudioPlayer.playing){
return AudioWrapper_State.Playing;
} else {
diff --git a/lib/utils/delegates.dart b/lib/utils/delegates.dart
index d6d3a73..fcbbe73 100644
--- a/lib/utils/delegates.dart
+++ b/lib/utils/delegates.dart
@@ -11,7 +11,7 @@ class ListenerReceipt {
}
class EventDelegate {
- final List> _receipts = [];
+ final List> _receipts = [];
ListenerReceipt addListener(Function(T) listener) {
final receipt = ListenerReceipt(listener);
@@ -26,14 +26,16 @@ class EventDelegate {
void trigger(T event) {
print("triggering event");
- for (var receipt in _receipts) {
- print("triggering listener");
- try {
- receipt.listener(event);
- } catch (e) {
- print("Error in listener: $e");
- removeListener(receipt);
+ try {
+ for (var receipt in _receipts) {
+ print("triggering listener");
+ try {
+ receipt.listener(event);
+ } catch (e) {
+ }
}
+ } catch (e) {
+ print("Error in trigger: $e");
}
}
}
diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc
index 1da8b5b..55cb301 100644
--- a/linux/flutter/generated_plugin_registrant.cc
+++ b/linux/flutter/generated_plugin_registrant.cc
@@ -7,16 +7,24 @@
#include "generated_plugin_registrant.h"
#include
+#include
#include
+#include
#include
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
+ g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
+ screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
+ g_autoptr(FlPluginRegistrar) window_manager_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
+ window_manager_plugin_register_with_registrar(window_manager_registrar);
g_autoptr(FlPluginRegistrar) window_to_front_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowToFrontPlugin");
window_to_front_plugin_register_with_registrar(window_to_front_registrar);
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index 69df1f4..d8082e0 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -4,7 +4,9 @@
list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_linux
+ screen_retriever
url_launcher_linux
+ window_manager
window_to_front
)
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 85b576f..3e8cf8a 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -9,11 +9,14 @@ import audio_session
import audioplayers_darwin
import device_info_plus
import flutter_web_auth_2
+import geolocator_apple
import just_audio
import package_info_plus
import path_provider_foundation
+import screen_retriever
import shared_preferences_foundation
import url_launcher_macos
+import window_manager
import window_to_front
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
@@ -21,10 +24,13 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin"))
+ GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
+ ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
+ WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin"))
}
diff --git a/pubspec.lock b/pubspec.lock
index 66d53d1..109d35a 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -272,6 +272,54 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ geolocator:
+ dependency: "direct main"
+ description:
+ name: geolocator
+ sha256: "694ec58afe97787b5b72b8a0ab78c1a9244811c3c10e72c4362ef3c0ceb005cd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.0.0"
+ geolocator_android:
+ dependency: transitive
+ description:
+ name: geolocator_android
+ sha256: "136f1c97e1903366393bda514c5d9e98843418baea52899aa45edae9af8a5cd6"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.5.2"
+ geolocator_apple:
+ dependency: transitive
+ description:
+ name: geolocator_apple
+ sha256: "2f2d4ee16c4df269e93c0e382be075cc01d5db6703c3196e4af20a634fe49ef4"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.6"
+ geolocator_platform_interface:
+ dependency: transitive
+ description:
+ name: geolocator_platform_interface
+ sha256: "009a21c4bc2761e58dccf07c24f219adaebe0ff707abdfd40b0a763d4003fab9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.2"
+ geolocator_web:
+ dependency: transitive
+ description:
+ name: geolocator_web
+ sha256: "49d8f846ebeb5e2b6641fe477a7e97e5dd73f03cbfef3fd5c42177b7300fb0ed"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.0"
+ geolocator_windows:
+ dependency: transitive
+ description:
+ name: geolocator_windows
+ sha256: a92fae29779d5c6dc60e8411302f5221ade464968fe80a36d330e80a71f087af
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.2"
google_fonts:
dependency: "direct main"
description:
@@ -496,6 +544,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
+ permission_handler:
+ dependency: "direct main"
+ description:
+ name: permission_handler
+ sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.3.0"
+ permission_handler_android:
+ dependency: transitive
+ description:
+ name: permission_handler_android
+ sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
+ url: "https://pub.dev"
+ source: hosted
+ version: "12.0.5"
+ permission_handler_apple:
+ dependency: transitive
+ description:
+ name: permission_handler_apple
+ sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.4.0"
+ permission_handler_html:
+ dependency: transitive
+ description:
+ name: permission_handler_html
+ sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.1"
+ permission_handler_platform_interface:
+ dependency: transitive
+ description:
+ name: permission_handler_platform_interface
+ sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.0"
+ permission_handler_windows:
+ dependency: transitive
+ description:
+ name: permission_handler_windows
+ sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1"
platform:
dependency: transitive
description:
@@ -544,6 +640,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.27.7"
+ screen_retriever:
+ dependency: transitive
+ description:
+ name: screen_retriever
+ sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.9"
shared_preferences:
dependency: "direct main"
description:
@@ -774,7 +878,7 @@ packages:
source: hosted
version: "3.1.1"
uuid:
- dependency: transitive
+ dependency: "direct main"
description:
name: uuid
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
@@ -782,7 +886,7 @@ packages:
source: hosted
version: "4.3.3"
vector_math:
- dependency: transitive
+ dependency: "direct main"
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
@@ -821,6 +925,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.2"
+ window_manager:
+ dependency: "direct main"
+ description:
+ name: window_manager
+ sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.8"
window_to_front:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 186bcb8..b456929 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -44,6 +44,12 @@ dependencies:
shared_preferences: ^2.2.2
url_launcher: ^6.2.2
ntp: ^2.0.0
+ uuid: ^4.3.3
+ window_manager: ^0.3.8
+ geolocator: ^11.0.0
+ vector_math: ^2.1.4
+ permission_handler: ^11.3.0
+
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
@@ -78,6 +84,7 @@ flutter:
- assets/fonts/ibus/london-buses-ibus.ttf
- assets/audio/manual_announcements/
- assets/audio/to_destination.wav
+ - assets/datasets/bus-blinds.csv
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index 4d83633..24fcf1e 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -7,17 +7,29 @@
#include "generated_plugin_registrant.h"
#include
+#include
#include
+#include
+#include
#include
+#include
#include
void RegisterPlugins(flutter::PluginRegistry* registry) {
AudioplayersWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
+ GeolocatorWindowsRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("GeolocatorWindows"));
JustAudioWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("JustAudioWindowsPlugin"));
+ PermissionHandlerWindowsPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
+ ScreenRetrieverPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
+ WindowManagerPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("WindowManagerPlugin"));
WindowToFrontPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WindowToFrontPlugin"));
}
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 40b0733..a9dab9a 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -4,8 +4,12 @@
list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_windows
+ geolocator_windows
just_audio_windows
+ permission_handler_windows
+ screen_retriever
url_launcher_windows
+ window_manager
window_to_front
)