| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
1
|
|
|
1
|
|
35560
|
use 5.16.0; |
|
|
1
|
|
|
|
|
3
|
|
|
2
|
1
|
|
|
1
|
|
479
|
use Map::Metro::Standard; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
3
|
1
|
|
|
1
|
|
12920
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
22
|
|
|
4
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
61
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Map::Metro { |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.2300'; # VERSION |
|
9
|
|
|
|
|
|
|
# ABSTRACT: Public transport graphing |
|
10
|
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
938
|
use Moose; |
|
|
1
|
|
|
|
|
463025
|
|
|
|
1
|
|
|
|
|
6
|
|
|
12
|
1
|
|
|
1
|
|
7773
|
use Module::Pluggable search_path => ['Map::Metro::Plugin::Map'], require => 1, sub_name => 'system_maps'; |
|
|
1
|
|
|
|
|
9185
|
|
|
|
1
|
|
|
|
|
9
|
|
|
13
|
1
|
|
|
1
|
|
955
|
use MooseX::AttributeShortcuts; |
|
|
1
|
|
|
|
|
403393
|
|
|
|
1
|
|
|
|
|
6
|
|
|
14
|
1
|
|
|
1
|
|
37380
|
use Types::Standard -types; |
|
|
1
|
|
|
|
|
65731
|
|
|
|
1
|
|
|
|
|
14
|
|
|
15
|
1
|
|
|
1
|
|
5135
|
use Types::Path::Tiny -types; |
|
|
1
|
|
|
|
|
22796
|
|
|
|
1
|
|
|
|
|
12
|
|
|
16
|
1
|
|
|
1
|
|
933
|
use List::Util 1.33 'any'; |
|
|
1
|
|
|
|
|
23
|
|
|
|
1
|
|
|
|
|
60
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
1
|
|
|
1
|
|
880
|
use Map::Metro::Graph; |
|
|
1
|
|
|
|
|
4
|
|
|
|
1
|
|
|
|
|
1331
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
has map => ( |
|
21
|
|
|
|
|
|
|
is => 'ro', |
|
22
|
|
|
|
|
|
|
traits => ['Array'], |
|
23
|
|
|
|
|
|
|
isa => ArrayRef, |
|
24
|
|
|
|
|
|
|
predicate => 1, |
|
25
|
|
|
|
|
|
|
handles => { |
|
26
|
|
|
|
|
|
|
get_map => 'get', |
|
27
|
|
|
|
|
|
|
}, |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
has mapclasses => ( |
|
30
|
|
|
|
|
|
|
is => 'ro', |
|
31
|
|
|
|
|
|
|
traits => ['Array'], |
|
32
|
|
|
|
|
|
|
isa => ArrayRef, |
|
33
|
|
|
|
|
|
|
default => sub { [] }, |
|
34
|
|
|
|
|
|
|
handles => { |
|
35
|
|
|
|
|
|
|
add_mapclass => 'push', |
|
36
|
|
|
|
|
|
|
get_mapclass => 'get', |
|
37
|
|
|
|
|
|
|
}, |
|
38
|
|
|
|
|
|
|
); |
|
39
|
|
|
|
|
|
|
has hooks => ( |
|
40
|
|
|
|
|
|
|
is => 'ro', |
|
41
|
|
|
|
|
|
|
isa => ArrayRef[ Str ], |
|
42
|
|
|
|
|
|
|
traits => ['Array'], |
|
43
|
|
|
|
|
|
|
default => sub { [] }, |
|
44
|
|
|
|
|
|
|
handles => { |
|
45
|
|
|
|
|
|
|
all_hooks => 'elements', |
|
46
|
|
|
|
|
|
|
hook_count => 'count', |
|
47
|
|
|
|
|
|
|
}, |
|
48
|
|
|
|
|
|
|
); |
|
49
|
|
|
|
|
|
|
has _plugin_ns => ( |
|
50
|
|
|
|
|
|
|
is => 'ro', |
|
51
|
|
|
|
|
|
|
isa => Str, |
|
52
|
|
|
|
|
|
|
default => 'Plugin::Map', |
|
53
|
|
|
|
|
|
|
init_arg => undef, |
|
54
|
|
|
|
|
|
|
); |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
around BUILDARGS => sub { |
|
57
|
|
|
|
|
|
|
my ($orig, $class, @args) = @_; |
|
58
|
|
|
|
|
|
|
my %args; |
|
59
|
|
|
|
|
|
|
if(scalar @args == 1) { |
|
60
|
|
|
|
|
|
|
$args{'map'} = shift @args; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
elsif(scalar @args % 2 != 0) { |
|
63
|
|
|
|
|
|
|
my $map = shift @args; |
|
64
|
|
|
|
|
|
|
%args = @args; |
|
65
|
|
|
|
|
|
|
$args{'map'} = $map; |
|
66
|
|
|
|
|
|
|
} |
|
67
|
|
|
|
|
|
|
else { |
|
68
|
|
|
|
|
|
|
%args = @args; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
if(exists $args{'map'} && !ArrayRef->check($args{'map'})) { |
|
72
|
|
|
|
|
|
|
$args{'map'} = [$args{'map'}]; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
if(exists $args{'hooks'} && !ArrayRef->check($args{'hooks'})) { |
|
75
|
|
|
|
|
|
|
$args{'hooks'} = [$args{'hooks'}]; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
return $class->$orig(%args); |
|
79
|
|
|
|
|
|
|
}; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub BUILD { |
|
82
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
83
|
0
|
|
|
|
|
|
my @args = @_; |
|
84
|
|
|
|
|
|
|
|
|
85
|
0
|
0
|
|
|
|
|
if($self->has_map) { |
|
86
|
0
|
|
|
|
|
|
my @system_maps = map { s{^Map::Metro::Plugin::Map::}{}; $_ } $self->system_maps; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
87
|
0
|
0
|
|
0
|
|
|
if(any { $_ eq $self->get_map(0) } @system_maps) { |
|
|
0
|
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
my $mapclass = 'Map::Metro::Plugin::Map::'.$self->get_map(0); |
|
89
|
0
|
|
|
|
|
|
my $mapobj = $mapclass->new(hooks => $self->hooks); |
|
90
|
0
|
|
|
|
|
|
$self->add_mapclass($mapobj); |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Borrowed from Mojo::Util |
|
96
|
|
|
|
|
|
|
sub decamelize { |
|
97
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
98
|
0
|
|
|
|
|
|
my $string = shift; |
|
99
|
|
|
|
|
|
|
|
|
100
|
0
|
0
|
|
|
|
|
return $string if $string !~ m{[A-Z]}; |
|
101
|
|
|
|
|
|
|
return join '_' => map { |
|
102
|
0
|
|
|
|
|
|
join ('_' => map { lc } grep { length } split m{([A-Z]{1}[^A-Z]*)}) |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
} split '::' => $string; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub parse { |
|
107
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
108
|
0
|
|
|
|
|
|
my %args = @_; |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
return Map::Metro::Graph->new(filepath => $self->get_mapclass(0)->maplocation, |
|
111
|
|
|
|
|
|
|
do_undiacritic => $self->get_mapclass(0)->do_undiacritic, |
|
112
|
|
|
|
|
|
|
wanted_hook_plugins => [$self->all_hooks], |
|
113
|
0
|
0
|
|
|
|
|
exists $args{'override_line_change_weight'} ? (override_line_change_weight => $args{'override_line_change_weight'}) : (), |
|
114
|
|
|
|
|
|
|
)->parse; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub available_maps { |
|
118
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
|
119
|
0
|
|
|
|
|
|
return sort $self->system_maps; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
1; |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
__END__ |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=pod |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=encoding utf-8 |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head1 NAME |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
Map::Metro - Public transport graphing |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=begin HTML |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
<p><img src="https://img.shields.io/badge/perl-5.16+-brightgreen.svg" alt="Requires Perl 5.16+" /> <a href="https://travis-ci.org/Csson/p5-Map-Metro"><img src="https://api.travis-ci.org/Csson/p5-Map-Metro.svg?branch=master" alt="Travis status" /></a></p> |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=end HTML |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=begin markdown |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
 [](https://travis-ci.org/Csson/p5-Map-Metro) |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=end markdown |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head1 VERSION |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
Version 0.2300, released 2016-01-14. |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Install a map |
|
157
|
|
|
|
|
|
|
$ cpanm Map::Metro::Plugin::Map::Stockholm |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# And then |
|
160
|
|
|
|
|
|
|
my $graph = Map::Metro->new('Stockholm', hooks => ['PrettyPrinter'])->parse; |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $routing = $graph->routing_for('Universitetet', 'Kista'); |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# or in a terminal |
|
165
|
|
|
|
|
|
|
$ map-metro.pl route Stockholm Universitetet Kista |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
prints |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
From Universitetet to Kista |
|
170
|
|
|
|
|
|
|
=========================== |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
-- Route 1 (cost 15) ---------- |
|
173
|
|
|
|
|
|
|
[ T14 ] Universitetet |
|
174
|
|
|
|
|
|
|
[ T14 ] Tekniska högskolan |
|
175
|
|
|
|
|
|
|
[ T14 ] Stadion |
|
176
|
|
|
|
|
|
|
[ T14 ] Ãstermalmstorg |
|
177
|
|
|
|
|
|
|
[ T14 ] T-Centralen |
|
178
|
|
|
|
|
|
|
[ * T11 ] T-Centralen |
|
179
|
|
|
|
|
|
|
[ T11 ] RÃ¥dhuset |
|
180
|
|
|
|
|
|
|
[ T11 ] Fridhemsplan |
|
181
|
|
|
|
|
|
|
[ T11 ] Stadshagen |
|
182
|
|
|
|
|
|
|
[ T11 ] Västra skogen |
|
183
|
|
|
|
|
|
|
[ T11 ] Solna centrum |
|
184
|
|
|
|
|
|
|
[ T11 ] Näckrosen |
|
185
|
|
|
|
|
|
|
[ T11 ] Hallonbergen |
|
186
|
|
|
|
|
|
|
[ T11 ] Kista |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
T11 Blue line |
|
189
|
|
|
|
|
|
|
T14 Red line |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
*: Transfer to other line |
|
192
|
|
|
|
|
|
|
+: Transfer to other station |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
The purpose of this distribution is to find the shortest L<unique|/"What is a unique path?"> route/routes between two stations in a transport network. |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
See L<Task::MapMetro::Maps> for a list of released maps. |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 Methods |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head3 new($city, hooks => []) |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
B<C<$city>> |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
The name of the city you want to search connections in. Mandatory, unless you are only going to call L</"available_maps">. |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
B<C<$hooks>> |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
Array reference of L<Hooks|Map::Metro::Hook> that listens for events. |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head3 parse() |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Returns a L<Map::Metro::Graph> object containing the entire graph. |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head3 available_maps() |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Returns an array reference containing the names of all Map::Metro maps installed on the system. |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head2 What is a unique path? |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
The following rules are a guideline: |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
If the starting station and finishing station... |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
...is on the same line there will be no transfers to other lines. |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
...shares multiple lines (e.g., both stations are on both line 2 and 4), each line constitutes a route. |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
...are on different lines a transfer will take place at a shared station. No matter how many shared stations there are, there will only be one route returned (but which transfer station is used can differ between queries). |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
...has no shared stations, the shortest route/routes will be returned. |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head1 MORE INFORMATION |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
L<Map::Metro::Graph> - How to use graph object. |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
L<Map::Metro::Plugin::Map> - How to make your own maps. |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
L<Map::Metro::Hook> - How to extend Map::Metro via hooks/events. |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
L<Map::Metro::Cmd> - A guide to the command line application. |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
L<Map::Metro::Graph::Connection> - Defines a MMG::Connection. |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
L<Map::Metro::Graph::Line> - Defines a MMG::Line. |
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
L<Map::Metro::Graph::LineStation> - Defines a MMG::LineStation. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
L<Map::Metro::Graph::Route> - Defines a MMG::Route. |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
L<Map::Metro::Graph::Routing> - Defines a MMG::Routing. |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
L<Map::Metro::Graph::Segment> - Defines a MMG::Segment. |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
L<Map::Metro::Graph::Station> - Defines a MMG::Station. |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
L<Map::Metro::Graph::Step> - Defines a MMG::Step. |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
L<Map::Metro::Graph::Transfer> - Defines a MMG::Transfer. |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head2 Hierarchy |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
The following is a conceptual overview of the various parts of a graph: |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
At first, the map file is parsed. The four types of blocks (stations, transfers, lines and segments) are translated |
|
267
|
|
|
|
|
|
|
into their respective object. |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Next, lines and stations are put together into L<LineStations|Map::Metro::Graph::LineStation>. Every two adjacent LineStations |
|
270
|
|
|
|
|
|
|
are put into two L<Connections|Map::Metro::Graph::Connection> (one for each direction). |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Now the network is complete, and it is time to start traversing it. |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
Once a request to search for paths between two stations is given, we first search for the starting L<Station|Map::Metro::Graph::Station> given either a |
|
275
|
|
|
|
|
|
|
station id or station name. Then we find all L<LineStations|Map::Metro::Graph::LineStation> for that station. |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Then we do the same for the destination station. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
And then we walk through the network, from L<LineStation|Map::Metro::Graph::LineStation> to L<LineStation|Map::Metro::Graph::LineStation>, finding their L<Connections|Map::Metro::Graph::Connection> |
|
280
|
|
|
|
|
|
|
and turning them into L<Steps|Map::Metro::Graph::Step>, which we then add to the L<Route|Map::Metro::Graph::Route>. |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
All L<Routes|Map::Metro::Graph::Route> between the two L<Stations|Map::Metro::Graph::Station> are then put into a L<Routing|Map::Metro::Graph::Routing>, which is returned to the user. |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=head1 PERFORMANCE |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
Since 0.2200 performance is less than an issue than it used to be, but it can still be improved. Prior to this version the entire network was analyzed up-front. This is unnecessary when searching one (or a few) routes. For long-running applications it is still possible to pre-calculate all paths, see L<asps|Map::Metro::Graph/"asps()">. |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head1 STATUS |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
This is somewhat experimental. I don't expect that the map file format will I<break>, but it might be |
|
291
|
|
|
|
|
|
|
extended. Only the documented api should be relied on, though breaking changes might occur. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
For all maps in the Map::Metro::Plugin::Map namespace (unless noted): |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
* These maps are not an official source. Use accordingly. |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
* There should be a note regarding what routes the map covers. |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 COMPATIBILITY |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
Currently requires Perl 5.16. |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head1 Map::Metro or Map::Tube? |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
L<Map::Tube> is the main alternative to C<Map::Metro>. They both have their strong and weak points. |
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
* Map::Tube is faster. |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
* Map::Tube is more stable: It has been on Cpan for a long time, and is under active development. |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
* Map::Metro has (in my opinion) a better map format. |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
* Map::Metro supports eg. transfers between stations. |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
* See L<Task::MapMetro::Maps> and L<Task::Map::Tube> for available maps. |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
* It is possible to convert Map::Metro maps into Map::Tube maps using L<map-metro.pl|Map::Metro::Cmd/"map-metro.pl metro_to_tube $city">. |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
L<Map::Tube> |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 SOURCE |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
L<https://github.com/Csson/p5-Map-Metro> |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 HOMEPAGE |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
L<https://metacpan.org/release/Map-Metro> |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 AUTHOR |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
Erik Carlsson <info@code301.com> |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
336
|
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
This software is copyright (c) 2016 by Erik Carlsson. |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
|
340
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |