File Coverage

blib/lib/Map/Metro/Graph.pm
Criterion Covered Total %
statement 433 643 67.3
branch 76 294 25.8
condition 13 55 23.6
subroutine 75 97 77.3
pod n/a
total 597 1089 54.8


line stmt bran cond sub pod time code
1 1     1   503 use Map::Metro::Standard::Moops;
  1         3  
  1         9  
2 1     1   17683 use strict;
  1         2  
  1         25  
3 1     1   5 use warnings;
  1         1  
  1         146  
4              
5             our $VERSION = '0.2300'; # VERSION
6             # PODNAME: Map::Metro::Graph
7             # ABSTRACT: An entire graph
8              
9 1     1   20559 class Map::Metro::Graph {
  1     1   35  
  1         8  
  1         3  
  1         60  
  1         5  
  1         2  
  1         10  
  1         303  
  1         2  
  1         8  
  1         62  
  1         2  
  1         51  
  1         5  
  1         2  
  1         98  
  1         34  
  1         6  
  1         2  
  1         8  
  1         4361  
  1         3  
  1         8  
  1         7675  
  1         110127  
  1         8  
  1         19243  
  1         3  
  1         16  
  1         1114  
  1         9682  
  1         13  
  1         1082  
  1         3169  
  1         8  
  1         1315  
  1         3  
  1         9  
  1         63089  
  1         5  
  1         5  
  1         2  
  1         29  
  1         5  
  1         2  
  1         44  
  1         5  
  1         2  
  1         161  
  1         10  
  1         5795  
  1         23  
  1         226  
  0         0  
10              
11 1     1   72491 use Graph;
  1         120563  
  1         48  
12              
13 1     1   681 use Map::Metro::Exception::LineIdDoesNotExistInLineList;
  1         4  
  1         51  
14 1     1   780 use Map::Metro::Exception::StationNameDoesNotExistInStationList;
  1         5  
  1         52  
15              
16 1     1   767 use Map::Metro::Graph::Connection;
  1         3  
  1         53  
17 1     1   720 use Map::Metro::Graph::Line;
  1         5  
  1         52  
18 1     1   708 use Map::Metro::Graph::LineStation;
  1         4  
  1         51  
19 1     1   729 use Map::Metro::Graph::Route;
  1         4  
  1         54  
20 1     1   724 use Map::Metro::Graph::Routing;
  1         3  
  1         52  
21 1     1   781 use Map::Metro::Graph::Segment;
  1         4  
  1         55  
22 1     1   845 use Map::Metro::Graph::Station;
  1         4  
  1         66  
23 1     1   731 use Map::Metro::Graph::Step;
  1         4  
  1         54  
24 1     1   732 use Map::Metro::Graph::Transfer;
  1         5  
  1         50  
25 1     1   693 use Map::Metro::Emitter;
  1         5  
  1         950  
26              
27 1         17 has filepath => (
28             is => 'ro',
29             isa => AbsFile,
30             required => 1,
31             );
32             has wanted_hook_plugins => (
33             is => 'ro',
34             isa => ArrayRef[Str],
35 0         0 default => sub { [] },
36 1         6430 traits => ['Array'],
37             predicate => 1,
38             handles => {
39             all_wanted_hook_plugins => 'elements',
40             }
41             );
42 1         9029 has do_undiacritic => (
43             is => 'rw',
44             isa => Bool,
45             default => 1,
46             );
47 1         4843 has default_line_change_weight => (
48             is => 'ro',
49             isa => Int,
50             default => 3,
51             );
52 1         4172 has override_line_change_weight => (
53             is => 'ro',
54             isa => Maybe[Int],
55             predicate => 1,
56             );
57             has emit => (
58             is => 'ro',
59             isa => Object,
60             init_arg => undef,
61             lazy => 1,
62 1         64 default => sub { Map::Metro::Emitter->new(wanted_hook_plugins => [shift->all_wanted_hook_plugins]) },
63 1         5950 handles => [qw/get_plugin all_plugins plugin_names/],
64             );
65              
66             has stations => (
67             is => 'ro',
68             traits => ['Array'],
69             isa => ArrayRef[ Station ],
70             predicate => 1,
71 1         32 default => sub { [] },
72 1         5467 init_arg => undef,
73             handles => {
74             add_station => 'push',
75             get_station => 'get',
76             find_station => 'first',
77             filter_stations => 'grep',
78             all_stations => 'elements',
79             station_count => 'count',
80             },
81             );
82             has lines => (
83             is => 'ro',
84             traits => ['Array'],
85             isa => ArrayRef[ Line ],
86             predicate => 1,
87 1         33 default => sub { [] },
88 1         18563 init_arg => undef,
89             handles => {
90             add_line => 'push',
91             find_line => 'first',
92             all_lines => 'elements',
93             },
94             );
95             has segments => (
96             is => 'ro',
97             traits => ['Array'],
98             isa => ArrayRef[ Segment ],
99             predicate => 1,
100 1         32 default => sub { [] },
101 1         13361 init_arg => undef,
102             handles => {
103             add_segment => 'push',
104             all_segments => 'elements',
105             filter_segments => 'grep',
106             },
107             );
108             has line_stations => (
109             is => 'ro',
110             traits => ['Array'],
111             isa => ArrayRef[ LineStation ],
112             predicate => 1,
113 1         32 default => sub { [] },
114 1         15143 init_arg => undef,
115             handles => {
116             add_line_station => 'push',
117             all_line_stations => 'elements',
118             line_station_count => 'count',
119             find_line_stations => 'grep',
120             find_line_station => 'first',
121             },
122             );
123             has connections => (
124             is => 'ro',
125             traits => ['Array'],
126             isa => ArrayRef[ Connection ],
127             predicate => 1,
128 1         33 default => sub { [] },
129 1         16901 init_arg => undef,
130             handles => {
131             add_connection => 'push',
132             all_connections => 'elements',
133             connection_count => 'count',
134             find_connection => 'first',
135             filter_connections => 'grep',
136             get_connection => 'get',
137             },
138             );
139             has transfers => (
140             is => 'ro',
141             traits => ['Array'],
142             isa => ArrayRef[ Transfer ],
143             predicate => 1,
144 1         32 default => sub { [] },
145 1         20504 init_arg => undef,
146             handles => {
147             add_transfer => 'push',
148             all_transfers => 'elements',
149             transfer_count => 'count',
150             get_transfer => 'get',
151             filter_transfers => 'grep',
152             },
153             );
154             has routings => (
155             is => 'ro',
156             traits => ['Array'],
157             isa => ArrayRef[ Routing ],
158             predicate => 1,
159 1         32 default => sub { [] },
160 1         18714 init_arg => undef,
161             handles => {
162             add_routing => 'push',
163             all_routings => 'elements',
164             routing_count => 'count',
165             find_routing => 'first',
166             filter_routings => 'grep',
167             get_routing => 'get',
168             },
169             );
170              
171 1         19905 has full_graph => (
172             is => 'ro',
173             lazy => 1,
174             predicate => 1,
175             builder => 1,
176             );
177              
178 1         5889 has asps => (
179             is => 'rw',
180             lazy => 1,
181             builder => 'calculate_shortest_paths',
182             predicate => 1,
183             init_arg => undef,
184             );
185              
186 1 0   1   1498 method _build_full_graph {
  1     0   3  
  1         229  
  1         5993  
  0         0  
  0         0  
187              
188 0         0 my $graph = Graph->new;
189              
190 0         0 foreach my $conn ($self->all_connections) {
191 0         0 $graph->add_weighted_edge($conn->origin_line_station->line_station_id,
192             $conn->destination_line_station->line_station_id,
193             $conn->weight);
194             }
195 0         0 return $graph;
196             }
197 1 0   1   1301 method calculate_shortest_paths {
  1     0   2  
  1         99  
  1         244  
  0         0  
  0         0  
198 0         0 return $self->full_graph->APSP_Floyd_Warshall;
199             }
200              
201 1 50   1   1211 method parse {
  1     1   3  
  1         106  
  1         152  
  1         5  
  1         2  
202 1         6 $self->build_network;
203 1         36 $self->construct_connections;
204              
205 1         16 return $self;
206             }
207              
208 1 50   1   1204 method build_network {
  1     1   3  
  1         501  
  1         151  
  1         4  
  1         2  
209 1         33 my @rows = split /\r?\n/ => $self->filepath->slurp_utf8;
210 1         1552 my $context = undef;
211              
212             ROW:
213 1         3 foreach my $row (@rows) {
214 49 100 66     895 next ROW if !length $row || $row =~ m{^[ \t]*#};
215              
216 44 100 66 8   146 if($row =~ m{^--(\w+)} && (any { $_ eq $1 } qw/stations transfers lines segments/)) {
  8         28  
217 3         6 $context = $1;
218 3         16 next ROW;
219             }
220              
221 41 50       247 $context eq 'stations' ? $self->add_station($row)
    100          
    50          
    100          
222             : $context eq 'transfers' ? $self->add_transfer($row)
223             : $context eq 'lines' ? $self->add_line($row)
224             : $context eq 'segments' ? $self->add_segment($row)
225             : ()
226             ;
227             }
228             }
229              
230 1 50   1   2939 around add_station(Str $text) {
  1 50   1   3  
  1 50   20   235  
  1 50       11  
  1 50       2  
  1 50       526  
  1         147  
  20         291  
  20         53  
  20         46  
  20         51  
  20         50  
  20         53  
  20         23  
  20         60  
  20         27  
231 20         61 $text = trim $text;
232 20         515 my @names = split m{\h*%\h*} => $text;
233 20         36 my $name = shift @names;
234              
235 20 50       65 if(my $station = $self->get_station_by_name($name, check => 0)) {
236 0         0 return $station;
237             }
238              
239 20         827 my $id = $self->station_count + 1;
240 20         159 my $station = Map::Metro::Graph::Station->new(original_name => $name, do_undiacritic => $self->do_undiacritic, eh $name, $id);
241              
242 20         78 foreach my $another_name (@names) {
243 0 0       0 if($another_name =~ m{^:(.+)}) {
244 0         0 $station->add_search_name($1);
245             }
246             else {
247 0         0 $station->add_alternative_name($another_name);
248             }
249             }
250 20         729 $self->emit->before_add_station($station);
251 20         829 $self->$next($station);
252             }
253              
254 1 0   1   2756 around add_transfer(Str $text) {
  1 0   1   2  
  1 0   0   242  
  1 0       6  
  1 0       2  
  1 0       251  
  1         1077  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
255 0         0 $text = trim $text;
256              
257 0         0 my($origin_station_name, $destination_station_name, $option_string) = split /\|/ => $text;
258 0         0 my $origin_station = $self->get_station_by_name($origin_station_name);
259 0         0 my $destination_station = $self->get_station_by_name($destination_station_name);
260              
261 0 0       0 my $options = defined $option_string ? $self->make_options($option_string, keys => [qw/weight/]) : {};
262              
263 0         0 my $transfer = Map::Metro::Graph::Transfer->new(origin_station => $origin_station,
264             destination_station => $destination_station,
265             %$options);
266              
267 0         0 $self->$next($transfer);
268             }
269              
270 1 50   1   2709 around add_line(Str $text) {
  1 50   1   2  
  1 50   2   229  
  1 50       7  
  1 50       3  
  1 50       233  
  1         760  
  2         32  
  2         8  
  2         6  
  2         7  
  2         7  
  2         7  
  2         3  
  2         9  
  2         3  
271 2         7 $text = trim $text;
272 2         57 my($id, $name, $description, $option_string) = split /\|/ => $text;
273              
274 2 50       7 my $options = defined $option_string ? $self->make_options($option_string, keys => [qw/color width/]) : {};
275 2         11 my $line = Map::Metro::Graph::Line->new(%{ $options }, id => $id, name => $name, description => $description);
  2         15  
276              
277 2         83 $self->$next($line);
278             }
279              
280 1 50   1   2759 around add_segment(Str $text) {
  1 50   1   3  
  1 50   19   238  
  1 50       7  
  1 50       2  
  1 50       1155  
  1         802  
  19         226  
  19         47  
  19         37  
  19         41  
  19         42  
  19         40  
  19         23  
  19         46  
  19         24  
281 19         50 $text = trim $text;
282 19         516 my($linestring, $start, $end, $option_string) = split /\|/ => $text;
283 19         49 my @line_ids_with_dir = split m/,/ => $linestring;
284 19         36 my @clean_line_ids = map { my $clean = $_ =~ s{[^a-z0-9]}{}gir; $clean } @line_ids_with_dir;
  24         55  
  24         69  
285              
286 19 50       47 my $options = defined $option_string ? $self->make_options($option_string, keys => [qw/dir/]) : {};
287              
288             #* Check that lines and stations in segments exist in the other lists
289 19         29 my($origin_station, $destination_station);
290              
291             try {
292 19     19   691 $self->get_line_by_id($_) foreach @clean_line_ids;
293 19         219 $origin_station = $self->get_station_by_name($start);
294 19         256 $destination_station = $self->get_station_by_name($end);
295             }
296             catch {
297 0     0   0 my $error = $_;
298 0 0       0 $error->does('Map::Metro::Exception') ? $error->out->fatal : die $error;
299 19         149 };
300 19         511 my @both_dir = ();
301 19         25 my @forward = ();
302 19         31 my @backward = ();
303 19         28 my @segments = ();
304              
305 19         33 foreach my $line_info (@line_ids_with_dir) {
306 24 50       91 if($line_info =~ m{^[a-z0-9]+$}i) {
    0          
    0          
307 24         59 push @both_dir => $line_info;
308             }
309             elsif($line_info =~ m{^([a-z0-9]+)->$}i) {
310 0         0 push @forward => $1;
311             }
312             elsif($line_info =~ m{^([a-z0-9]+)<-$}i) {
313 0         0 push @backward => $1;
314             }
315             }
316              
317 19 50       46 if(scalar @both_dir) {
318 19         48 push @segments => Map::Metro::Graph::Segment->new(line_ids => \@both_dir, origin_station => $origin_station, destination_station => $destination_station);
319             }
320 19 50       55 if(scalar @forward) {
321 0         0 push @segments => Map::Metro::Graph::Segment->new(line_ids => \@forward, is_one_way => 1, origin_station => $origin_station, destination_station => $destination_station);
322             }
323 19 50       36 if(scalar @backward) {
324 0         0 push @segments => Map::Metro::Graph::Segment->new(line_ids => \@backward, is_one_way => 1, origin_station => $destination_station, destination_station => $origin_station);
325             }
326              
327 19         746 $self->$next(@segments);
328             }
329              
330 1 50   1   2243 around add_line_station($line_station) {
  1 50   48   1  
  1 50       258  
  1 50       784  
  48         557  
  48         111  
  48         109  
  48         113  
  48         100  
  48         53  
331 48         1540 my $exists = $self->get_line_station_by_line_and_station_id($line_station->line->id, $line_station->station->id);
332 48 100       4204 return $exists if $exists;
333              
334 26         1061 $self->$next($line_station);
335 26         358 return $line_station;
336             }
337              
338 1 50   1   2378 method get_line_by_id(Str $line_id) {
  1 50   1   2  
  1 50   48   183  
  1 50       9  
  1 50       3  
  1         151  
  1         758  
  48         155  
  48         120  
  48         107  
  48         104  
  48         47  
  48         125  
  48         58  
339 70     70   2463 return $self->find_line(sub { $_->id eq $line_id })
340 48   33     1918 || Map::Metro::Exception::::LineIdDoesNotExistInLineList->throw(line_id => $line_id);
341             }
342 1 50 33 1   9420 method get_station_by_name(Str $station_name, :$check = 1 ) {
  1 50 50 1   2  
  1 50   1   207  
  1 50   58   6  
  1 50       2  
  1 50       97  
  1 100       5  
  1         2  
  1         919  
  1         158  
  58         150  
  58         129  
  58         146  
  58         141  
  58         62  
  58         151  
  58         93  
  58         87  
  58         302  
  0         0  
  58         80  
  58         157  
  58         254  
  58         197  
  58         69  
343 58     589   2529 my $station = $self->find_station(sub { fc($_->name) eq fc($station_name) });
  589         20385  
344 58 100       595 return $station if Station->check($station);
345              
346 20 50       341 if($check) {
347 0     0   0 $station = $self->find_station(sub { fc($_->original_name) eq fc($station_name) });
  0         0  
348 0 0       0 return $station if Station->check($station);
349              
350             $station = $self->find_station(sub {
351 0     0   0 my $current_station = $_;
352 0 0       0 if(any { fc($station_name) eq fc($_) } $current_station->all_alternative_names) {
  0         0  
353 0         0 return $current_station;
354             }
355 0         0 });
356 0 0       0 return $station if Station->check($station);
357              
358             $station = $self->find_station(sub {
359 0     0   0 my $current_station = $_;
360 0 0       0 if(any { fc($station_name) eq fc($_) } $current_station->all_search_names) {
  0         0  
361 0         0 return $current_station;
362             }
363 0         0 });
364 0 0       0 return $station if Station->check($station);
365             }
366              
367 20 50       94 Map::Metro::Exception::StationNameDoesNotExistInStationList->throw(station_name => $station_name) if $check;
368             }
369 1 0 0 1   2401 method get_station_by_id(Int $id) {
  1 0   1   2  
  1 0   0   176  
  1 0       7  
  1 0       3  
  1         202  
  1         166  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
370 0     0   0 return $self->find_station(sub { $_->id == $id })
371 0   0     0 || StationIdDoesNotExist->throw(station_id => $id);
372             }
373 1 50   1   2378 method get_line_stations_by_station(Station $station) {
  1 50   1   2  
  1 50   20   188  
  1 50       6  
  1 50       2  
  1         139  
  1         151  
  20         48  
  20         49  
  20         40  
  20         64  
  20         21  
  20         64  
  20         24  
374 20     520   909 return $self->find_line_stations(sub { $_->station->id == $station->id });
  520         55895  
375             }
376 1 50   1   2387 method get_line_station_by_line_and_station_id($line_id, $station_id) {
  1 50   96   3  
  1 50       245  
  1 50       157  
  96         6404  
  96         199  
  96         235  
  96         201  
  96         99  
377 96 100   1230   3998 return $self->find_line_station(sub { $_->line->id eq $line_id && $_->station->id == $station_id });
  1230         108485  
378             }
379 1 0 0 1   2379 method get_line_station_by_id(Int $line_station_id) {
  1 0   1   2  
  1 0   0   182  
  1 0       9  
  1 0       2  
  1         179  
  1         156  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
380 0     0   0 return $self->find_line_station(sub { $_->line_station_id == $line_station_id });
  0         0  
381             }
382 1 0 0 1   3637 method get_connection_by_line_station_ids(Int $first_ls_id, Int $second_ls_id) {
  1 0 0 1   3  
  1 0   1   190  
  1 0   0   6  
  1 0       2  
  1 0       224  
  1 0       6  
  1 0       2  
  1         234  
  1         154  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
383 0         0 my $first_ls = $self->get_line_station_by_id($first_ls_id);
384 0         0 my $second_ls = $self->get_line_station_by_id($second_ls_id);
385              
386             return $self->find_connection(
387             sub {
388 0 0   0   0 $_->origin_line_station->line_station_id == $first_ls->line_station_id
389             && $_->destination_line_station->line_station_id == $second_ls->line_station_id
390             }
391 0         0 );
392             }
393 1 0   1   1286 method next_line_station_id {
  1     0   2  
  1         97  
  1         156  
  0         0  
  0         0  
394 0         0 return $self->line_station_count + 1;
395             }
396 1 0 0 1   4345 method make_options(Str $string, ArrayRef[Str] :$keys = []) {
  1 0 0 1   3  
  1 0   1   185  
  1 0   1   5  
  1 0   0   3  
  1 0       101  
  1 0       7  
  1 0       2  
  1         260  
  1         10  
  1         3  
  1         392  
  1         148  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
397 0         0 my $options = {};
398 0         0 my @options = split /, ?/ => $string;
399              
400             OPTION:
401 0         0 foreach my $option (@options) {
402 0         0 my($key, $value) = split /:/ => $option;
403              
404 0 0 0 0   0 next OPTION if scalar @$keys && (none { $key eq $_ } @$keys);
  0         0  
405 0         0 $options->{ $key } = $value;
406             }
407 0         0 return $options;
408             }
409              
410 1 50   1   1305 method construct_connections {
  1     1   3  
  1         1212  
  1         164  
  1         6  
  1         3  
411 1 50 33     42 if(!($self->has_stations && $self->has_lines && $self->has_segments)) {
      33        
412 0         0 IncompleteParse->throw;
413             }
414              
415             #* Walk through all segments, and all lines for
416             #* that segment. Add pairwise connections between
417             #* all pair of stations on the same line
418 1         94 my $next_line_station_id = 0;
419             SEGMENT:
420 1         43 foreach my $segment ($self->all_segments) {
421              
422             LINE:
423 19         1705 foreach my $line_id ($segment->all_line_ids) {
424 24         457 my $line = $self->get_line_by_id($line_id);
425              
426 24   66     936 my $origin_line_station = $self->get_line_station_by_line_and_station_id($line_id, $segment->origin_station->id)
427             ||
428             Map::Metro::Graph::LineStation->new(
429             line_station_id => ++$next_line_station_id,
430             station => $segment->origin_station,
431             line => $line,
432             );
433 24         2173 $origin_line_station = $self->add_line_station($origin_line_station);
434 24         740 $segment->origin_station->add_line($line);
435              
436 24   66     1302 my $destination_line_station = $self->get_line_station_by_line_and_station_id($line_id, $segment->destination_station->id)
437             ||
438             Map::Metro::Graph::LineStation->new(
439             line_station_id => ++$next_line_station_id,
440             station => $segment->destination_station,
441             line => $line,
442             );
443 24         251 $destination_line_station = $self->add_line_station($destination_line_station);
444 24         771 $segment->destination_station->add_line($line);
445              
446 24         1410 my $weight = 1;
447              
448 24         75 my $conn = Map::Metro::Graph::Connection->new(origin_line_station => $origin_line_station,
449             destination_line_station => $destination_line_station,
450             weight => $weight);
451              
452 24         72 my $inv_conn = Map::Metro::Graph::Connection->new(origin_line_station => $destination_line_station,
453             destination_line_station => $origin_line_station,
454             weight => $weight);
455              
456 24         788 $origin_line_station->station->add_connecting_station($destination_line_station->station);
457 24 50       1995 $destination_line_station->station->add_connecting_station($origin_line_station->station) if !$segment->is_one_way;
458              
459 24         2218 $self->add_connection($conn);
460 24 50       962 $self->add_connection($inv_conn) if !$segment->is_one_way;
461             }
462             }
463              
464             #* Walk through all stations, and fetch all line_stations per station
465             #* Then add a connection between all line_stations of every station
466             STATION:
467 1         101 foreach my $station ($self->all_stations) {
468 20         133 my @line_stations_at_station = $self->get_line_stations_by_station($station);
469              
470             LINE_STATION:
471 20         884 foreach my $line_station (@line_stations_at_station) {
472 26         121 my @other_line_stations = grep { $_->line_station_id != $line_station->line_station_id } @line_stations_at_station;
  38         1402  
473              
474             OTHER_LINE_STATION:
475 26         309 foreach my $other_line_station (@other_line_stations) {
476              
477 12 50       560 my $weight = $self->has_override_line_change_weight ? $self->override_line_change_weight : $self->default_line_change_weight;
478 12         503 my $conn = Map::Metro::Graph::Connection->new(origin_line_station => $line_station,
479             destination_line_station => $other_line_station,
480             weight => $weight);
481 12         517 $self->add_connection($conn);
482             }
483             }
484             }
485              
486             #* Walk through all transfers, and add connections between all line stations of the two stations
487             TRANSFER:
488 1         48 foreach my $transfer ($self->all_transfers) {
489 0           my $origin_station = $transfer->origin_station;
490 0           my $destination_station = $transfer->destination_station;
491 0           my @line_stations_at_origin = $self->get_line_stations_by_station($origin_station);
492              
493             ORIGIN_LINE_STATION:
494 0           foreach my $origin_line_station (@line_stations_at_origin) {
495 0           my @line_stations_at_destination = $self->get_line_stations_by_station($destination_station);
496              
497             DESTINATION_LINE_STATION:
498 0           foreach my $destination_line_station (@line_stations_at_destination) {
499              
500 0           my $conn = Map::Metro::Graph::Connection->new(origin_line_station => $origin_line_station,
501             destination_line_station => $destination_line_station,
502             weight => $transfer->weight);
503              
504 0           my $inv_conn = Map::Metro::Graph::Connection->new(origin_line_station => $destination_line_station,
505             destination_line_station => $origin_line_station,
506             weight => $transfer->weight);
507              
508 0           $origin_line_station->station->add_connecting_station($destination_line_station->station);
509 0           $destination_line_station->station->add_connecting_station($origin_line_station->station);
510              
511 0           $self->add_connection($conn);
512 0           $self->add_connection($inv_conn);
513             }
514             }
515              
516             }
517             }
518              
519             method ensure_station(Int|Str|Station $place
520             --> Station but assumed
521 1 0   1   15295 ) {
  1 0   1   3  
  1 0   0   176  
  1 0       6  
  1 0       2  
  1         312  
  1         151  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
522              
523 0 0         return $place if Station->check($place);
524              
525             try {
526 0 0   0     if(Int->check($place)) {
527 0           $place = $self->get_station_by_id($place);
528             }
529             else {
530 0           $place = $self->get_station_by_name($place);
531             }
532             }
533             catch {
534 0     0     my $error = $_;
535 0 0         $error->does('Map::Metro::Exception') ? $error->throw : die $error;
536 0           };
537 0           return $place;
538             }
539              
540             method routing_for(Int|Str|Station $origin! does doc('The first station. Station id, name or object.'),
541             Int|Str|Station $destination! does doc('The final station. Station id, name or object.')
542             --> Routing but assumed
543 1 0   1   11994 ) {
  1 0   1   2  
  1 0   1   200  
  1 0   0   5  
  1 0       2  
  1 0       157  
  1 0       6  
  1 0       3  
  1         1237  
  1         220  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
544              
545 0           my $origin_station = $self->ensure_station($origin);
546 0           my $destination_station = $self->ensure_station($destination);
547              
548 0           my @origin_line_station_ids = map { $_->line_station_id } $self->get_line_stations_by_station($origin_station);
  0            
549 0           my @destination_line_station_ids = map { $_->line_station_id } $self->get_line_stations_by_station($destination_station);
  0            
550              
551 0 0         if($self->has_routings) {
552 0 0   0     my $existing_routing = $self->find_routing(sub { $_->origin_station->id == $origin_station->id && $_->destination_station->id == $destination_station->id });
  0            
553 0 0         return $existing_routing if $existing_routing;
554             }
555 0           $self->emit->before_start_routing;
556 0           my $routing = Map::Metro::Graph::Routing->new(origin_station => $origin_station, destination_station => $destination_station);
557              
558             #* Find all lines going from origin station
559             #* Find all lines going to destination station
560             #* Get all routes between them
561             #* and then, in the third and fourth for, loop over the
562             #* found routes and add info about all stations on all lines
563             ORIGIN_LINE_STATION:
564 0           foreach my $origin_id (@origin_line_station_ids) {
565 0           my $origin = $self->get_line_station_by_id($origin_id);
566              
567             DESTINATION_LINE_STATION:
568 0           foreach my $dest_id (@destination_line_station_ids) {
569 0           my $dest = $self->get_line_station_by_id($dest_id);
570              
571 0 0         my $graphroute = [ $self->has_asps ? $self->asps->path_vertices($origin_id, $dest_id) : $self->full_graph->SP_Dijkstra($origin_id, $dest_id) ];
572              
573 0 0 0       if($origin->possible_on_same_line($dest) && !$origin->on_same_line($dest)) {
574 0           next DESTINATION_LINE_STATION;
575             }
576              
577 0           my $route = Map::Metro::Graph::Route->new;
578              
579 0           my($prev_step, $prev_conn, $next_step, $next_conn);
580              
581             LINE_STATION:
582 0           foreach my $index (0 .. scalar @$graphroute - 2) {
583 0           my $this_line_station_id = $graphroute->[ $index ];
584 0           my $next_line_station_id = $graphroute->[ $index + 1 ];
585 0   0       my $next_next_line_station_id = $graphroute->[ $index + 2 ] // undef;
586              
587              
588              
589 0           my $conn = $self->get_connection_by_line_station_ids($this_line_station_id, $next_line_station_id);
590              
591             #* Don't continue beyond this route, even it connections exist.
592 0 0         if($index + 2 < scalar @$graphroute) {
593 0 0         $next_conn = defined $next_next_line_station_id ? $self->get_connection_by_line_station_ids($this_line_station_id, $next_line_station_id) : undef;
594 0 0         $next_step = Map::Metro::Graph::Step->new(from_connection => $next_conn) if defined $next_conn;
595             }
596             else {
597 0           $next_conn = $next_step = undef;
598             }
599              
600 0           my $step = Map::Metro::Graph::Step->new(from_connection => $conn);
601 0 0         $step->previous_step($prev_step) if $prev_step;
602 0 0         $step->next_step($next_step) if $next_step;
603              
604 0 0         $next_step->previous_step($step) if defined $next_step;
605              
606 0           $route->add_step($step);
607 0           $prev_step = $step;
608 0           $step = $next_step;
609              
610             }
611              
612             LINE_STATION:
613 0           foreach my $index (0 .. scalar @$graphroute - 1) {
614 0           my $line_station = $self->get_line_station_by_id($graphroute->[$index]);
615              
616 0           $route->add_line_station($line_station);
617             }
618              
619 0 0         next DESTINATION_LINE_STATION if $route->transfer_on_first_station;
620 0 0         next DESTINATION_LINE_STATION if $route->transfer_on_final_station;
621              
622 0           $routing->add_route($route);
623             }
624             }
625 0 0         $self->emit->before_add_routing($routing) if $self->has_wanted_hook_plugins;
626 0           $self->add_routing($routing);
627              
628 0           return $routing;
629             }
630              
631 1 0   1   7969 method all_pairs(--> ArrayRef[Routing] but assumed does doc('Routings between every pair of Stations')) {
  1 0   0   2  
  1         426  
  1         184  
  0            
  0            
  0            
632              
633 0           my $routings = [];
634 0           $self->calculate_shortest_paths;
635              
636             STATION:
637 0           foreach my $station ($self->all_stations) {
638 0           my @other_stations = grep { $_->id != $station->id } $self->all_stations;
  0            
639              
640             OTHER_STATION:
641 0           foreach my $other_station (@other_stations) {
642 0           push @$routings => $self->routing_for($station, $other_station);
643             }
644             }
645 0           return $routings;
646             }
647              
648             }
649              
650             1;
651              
652             __END__
653              
654             =pod
655              
656             =encoding UTF-8
657              
658             =head1 NAME
659              
660             Map::Metro::Graph - An entire graph
661              
662             =head1 VERSION
663              
664             Version 0.2300, released 2016-01-14.
665              
666              
667              
668             =head1 SYNOPSIS
669              
670             my $graph = Map::Metro->new('Stockholm')->parse;
671              
672             my $routing = $graph->routing_for('Universitetet', 'Kista');
673              
674             # And then it's traversing time. Also see the
675             # Map::Metro::Plugin::Hook::PrettyPrinter hook
676             say $routing->origin_station->name;
677             say $routing->destination_station->name;
678              
679             foreach my $route ($routing->all_routes) {
680             foreach my $step ($route->all_steps) {
681             say 'Transfer!' if $step->was_line_transfer;
682             say $step->origin_line_station->line->id;
683             say $step->origin_line_station->station->name;
684             }
685             say '----';
686             }
687              
688             #* The constructed Graph object is also available
689             my $full_graph = $graph->full_graph;
690              
691             =head1 DESCRIPTION
692              
693             This class is at the core of L<Map::Metro>. After a map has been parsed the returned instance of this class contains
694             the entire network (graph) in a hierarchy of objects.
695              
696             =head1 ATTRIBUTES
697              
698              
699             =head2 filepath
700              
701             =begin HTML
702              
703             <table cellpadding="0" cellspacing="0">
704             <tr>
705             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Path::Tiny#AbsFile">AbsFile</a></td>
706             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">required</td>
707             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
708             </tr>
709             </table>
710              
711             <p></p>
712              
713             =end HTML
714              
715             =begin markdown
716              
717             <table cellpadding="0" cellspacing="0">
718             <tr>
719             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Path::Tiny#AbsFile">AbsFile</a></td>
720             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">required</td>
721             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
722             </tr>
723             </table>
724              
725             <p></p>
726              
727             =end markdown
728              
729             =head2 default_line_change_weight
730              
731             =begin HTML
732              
733             <table cellpadding="0" cellspacing="0">
734             <tr>
735             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a></td>
736             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>3</code></td>
737             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
738             </tr>
739             </table>
740              
741             <p></p>
742              
743             =end HTML
744              
745             =begin markdown
746              
747             <table cellpadding="0" cellspacing="0">
748             <tr>
749             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a></td>
750             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>3</code></td>
751             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
752             </tr>
753             </table>
754              
755             <p></p>
756              
757             =end markdown
758              
759             =head2 do_undiacritic
760              
761             =begin HTML
762              
763             <table cellpadding="0" cellspacing="0">
764             <tr>
765             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a></td>
766             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>1</code></td>
767             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read/write</td>
768             </tr>
769             </table>
770              
771             <p></p>
772              
773             =end HTML
774              
775             =begin markdown
776              
777             <table cellpadding="0" cellspacing="0">
778             <tr>
779             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a></td>
780             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>1</code></td>
781             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read/write</td>
782             </tr>
783             </table>
784              
785             <p></p>
786              
787             =end markdown
788              
789             =head2 full_graph
790              
791             =begin HTML
792              
793             <table cellpadding="0" cellspacing="0">
794             <tr>
795             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional</td>
796             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
797             </tr>
798             </table>
799              
800             <p></p>
801              
802             =end HTML
803              
804             =begin markdown
805              
806             <table cellpadding="0" cellspacing="0">
807             <tr>
808             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional</td>
809             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
810             </tr>
811             </table>
812              
813             <p></p>
814              
815             =end markdown
816              
817             =head2 override_line_change_weight
818              
819             =begin HTML
820              
821             <table cellpadding="0" cellspacing="0">
822             <tr>
823             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Maybe">Maybe</a> [ <a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> ]</td>
824             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional</td>
825             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
826             </tr>
827             </table>
828              
829             <p></p>
830              
831             =end HTML
832              
833             =begin markdown
834              
835             <table cellpadding="0" cellspacing="0">
836             <tr>
837             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Maybe">Maybe</a> [ <a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> ]</td>
838             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional</td>
839             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
840             </tr>
841             </table>
842              
843             <p></p>
844              
845             =end markdown
846              
847             =head2 wanted_hook_plugins
848              
849             =begin HTML
850              
851             <table cellpadding="0" cellspacing="0">
852             <tr>
853             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
854             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default is a <code>coderef</code></td>
855             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
856             </tr>
857             </table>
858              
859             <p></p>
860              
861             =end HTML
862              
863             =begin markdown
864              
865             <table cellpadding="0" cellspacing="0">
866             <tr>
867             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> ]</td>
868             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default is a <code>coderef</code></td>
869             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
870             </tr>
871             </table>
872              
873             <p></p>
874              
875             =end markdown
876              
877             =head2 asps
878              
879             =begin HTML
880              
881             <table cellpadding="0" cellspacing="0">
882             <tr>
883             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
884             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read/write</td>
885             </tr>
886             </table>
887              
888             <p></p>
889              
890             =end HTML
891              
892             =begin markdown
893              
894             <table cellpadding="0" cellspacing="0">
895             <tr>
896             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
897             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read/write</td>
898             </tr>
899             </table>
900              
901             <p></p>
902              
903             =end markdown
904              
905             =head2 connections
906              
907             =begin HTML
908              
909             <table cellpadding="0" cellspacing="0">
910             <tr>
911             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Connection">Connection</a> ]</td>
912             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
913             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
914             </tr>
915             </table>
916              
917             <p></p>
918              
919             =end HTML
920              
921             =begin markdown
922              
923             <table cellpadding="0" cellspacing="0">
924             <tr>
925             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Connection">Connection</a> ]</td>
926             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
927             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
928             </tr>
929             </table>
930              
931             <p></p>
932              
933             =end markdown
934              
935             =head2 emit
936              
937             =begin HTML
938              
939             <table cellpadding="0" cellspacing="0">
940             <tr>
941             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Object">Object</a></td>
942             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
943             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
944             </tr>
945             </table>
946              
947             <p></p>
948              
949             =end HTML
950              
951             =begin markdown
952              
953             <table cellpadding="0" cellspacing="0">
954             <tr>
955             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Object">Object</a></td>
956             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
957             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
958             </tr>
959             </table>
960              
961             <p></p>
962              
963             =end markdown
964              
965             =head2 line_stations
966              
967             =begin HTML
968              
969             <table cellpadding="0" cellspacing="0">
970             <tr>
971             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#LineStation">LineStation</a> ]</td>
972             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
973             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
974             </tr>
975             </table>
976              
977             <p></p>
978              
979             =end HTML
980              
981             =begin markdown
982              
983             <table cellpadding="0" cellspacing="0">
984             <tr>
985             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#LineStation">LineStation</a> ]</td>
986             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
987             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
988             </tr>
989             </table>
990              
991             <p></p>
992              
993             =end markdown
994              
995             =head2 lines
996              
997             =begin HTML
998              
999             <table cellpadding="0" cellspacing="0">
1000             <tr>
1001             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Line">Line</a> ]</td>
1002             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1003             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1004             </tr>
1005             </table>
1006              
1007             <p></p>
1008              
1009             =end HTML
1010              
1011             =begin markdown
1012              
1013             <table cellpadding="0" cellspacing="0">
1014             <tr>
1015             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Line">Line</a> ]</td>
1016             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1017             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1018             </tr>
1019             </table>
1020              
1021             <p></p>
1022              
1023             =end markdown
1024              
1025             =head2 routings
1026              
1027             =begin HTML
1028              
1029             <table cellpadding="0" cellspacing="0">
1030             <tr>
1031             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Routing">Routing</a> ]</td>
1032             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1033             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1034             </tr>
1035             </table>
1036              
1037             <p></p>
1038              
1039             =end HTML
1040              
1041             =begin markdown
1042              
1043             <table cellpadding="0" cellspacing="0">
1044             <tr>
1045             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Routing">Routing</a> ]</td>
1046             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1047             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1048             </tr>
1049             </table>
1050              
1051             <p></p>
1052              
1053             =end markdown
1054              
1055             =head2 segments
1056              
1057             =begin HTML
1058              
1059             <table cellpadding="0" cellspacing="0">
1060             <tr>
1061             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Segment">Segment</a> ]</td>
1062             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1063             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1064             </tr>
1065             </table>
1066              
1067             <p></p>
1068              
1069             =end HTML
1070              
1071             =begin markdown
1072              
1073             <table cellpadding="0" cellspacing="0">
1074             <tr>
1075             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Segment">Segment</a> ]</td>
1076             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1077             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1078             </tr>
1079             </table>
1080              
1081             <p></p>
1082              
1083             =end markdown
1084              
1085             =head2 stations
1086              
1087             =begin HTML
1088              
1089             <table cellpadding="0" cellspacing="0">
1090             <tr>
1091             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a> ]</td>
1092             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1093             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1094             </tr>
1095             </table>
1096              
1097             <p></p>
1098              
1099             =end HTML
1100              
1101             =begin markdown
1102              
1103             <table cellpadding="0" cellspacing="0">
1104             <tr>
1105             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a> ]</td>
1106             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1107             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1108             </tr>
1109             </table>
1110              
1111             <p></p>
1112              
1113             =end markdown
1114              
1115             =head2 transfers
1116              
1117             =begin HTML
1118              
1119             <table cellpadding="0" cellspacing="0">
1120             <tr>
1121             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Transfer">Transfer</a> ]</td>
1122             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1123             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1124             </tr>
1125             </table>
1126              
1127             <p></p>
1128              
1129             =end HTML
1130              
1131             =begin markdown
1132              
1133             <table cellpadding="0" cellspacing="0">
1134             <tr>
1135             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Transfer">Transfer</a> ]</td>
1136             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">not in constructor</td>
1137             <td style="padding-left: 6px; padding-right: 6px; white-space: nowrap;">read-only</td>
1138             </tr>
1139             </table>
1140              
1141             <p></p>
1142              
1143             =end markdown
1144              
1145             =head1 METHODS
1146              
1147              
1148             =head2 routing_for
1149              
1150             =begin HTML
1151              
1152             <p></p>
1153              
1154             <!-- -->
1155             <table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
1156              
1157             <tr style="vertical-align: top;">
1158             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">Positional parameters</td>
1159             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1160             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1161             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1162             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1163             </tr>
1164             <tr style="vertical-align: top;">
1165             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$origin</code></td>
1166             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> | <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> | <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a></td>
1167             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
1168             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
1169             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">The first station. Station id, name or object.<br /></td>
1170             </tr>
1171             <tr style="vertical-align: top;">
1172             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$destination</code></td>
1173             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> | <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> | <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a></td>
1174             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
1175             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
1176             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">The final station. Station id, name or object.<br /></td>
1177             </tr>
1178             <tr style="vertical-align: top;">
1179             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">Returns</td>
1180             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1181             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1182             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1183             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1184             </tr>
1185             <tr style="vertical-align: top;">
1186             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Map::Metro::Types#Routing">Routing</a></td>
1187             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1188             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1189             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1190             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1191             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;"></td>
1192             </tr>
1193             </table>
1194              
1195             =end HTML
1196              
1197             =begin markdown
1198              
1199             <p></p>
1200              
1201             <!-- -->
1202             <table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
1203              
1204             <tr style="vertical-align: top;">
1205             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">Positional parameters</td>
1206             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1207             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1208             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1209             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #eee8e8;">&#160;</td>
1210             </tr>
1211             <tr style="vertical-align: top;">
1212             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$origin</code></td>
1213             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> | <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> | <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a></td>
1214             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
1215             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
1216             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">The first station. Station id, name or object.<br /></td>
1217             </tr>
1218             <tr style="vertical-align: top;">
1219             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$destination</code></td>
1220             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a> | <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> | <a href="https://metacpan.org/pod/Map::Metro::Types#Station">Station</a></td>
1221             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
1222             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
1223             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">The final station. Station id, name or object.<br /></td>
1224             </tr>
1225             <tr style="vertical-align: top;">
1226             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">Returns</td>
1227             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1228             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1229             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1230             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1231             </tr>
1232             <tr style="vertical-align: top;">
1233             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Map::Metro::Types#Routing">Routing</a></td>
1234             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1235             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1236             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1237             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">&#160;</td>
1238             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;"></td>
1239             </tr>
1240             </table>
1241              
1242             =end markdown
1243              
1244              
1245             =head2 all_pairs
1246              
1247             =begin HTML
1248              
1249             <p></p>
1250              
1251             <!-- -->
1252             <table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
1253              
1254             <tr style="vertical-align: top;">
1255             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">Returns</td>
1256             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1257             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1258             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1259             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1260             </tr>
1261             <tr style="vertical-align: top;">
1262             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Routing">Routing</a> ]</td>
1263             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1264             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1265             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1266             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Routings between every pair of Stations</td>
1267             </tr>
1268             </table>
1269              
1270             =end HTML
1271              
1272             =begin markdown
1273              
1274             <p></p>
1275              
1276             <!-- -->
1277             <table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
1278              
1279             <tr style="vertical-align: top;">
1280             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">Returns</td>
1281             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1282             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1283             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1284             <td style="text-align: left; color: #444; padding-left: 5px; font-weight: bold; background-color: #e8e8ee;">&#160;</td>
1285             </tr>
1286             <tr style="vertical-align: top;">
1287             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a> [ <a href="https://metacpan.org/pod/Types::Standard#Routing">Routing</a> ]</td>
1288             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1289             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1290             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
1291             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Routings between every pair of Stations</td>
1292             </tr>
1293             </table>
1294              
1295             =end markdown
1296              
1297             =head2 asps
1298              
1299             This class uses L<Graph> under the hood. This method returns the L<Graph/"All-Pairs Shortest Paths (APSP)"> object returned
1300             by the APSP_Floyd_Warshall() method. If you prefer to traverse the graph via this object, observe that the vertices is identified
1301             by their C<line_station_id> in L<Map::Metro::Graph::LineStation>.
1302              
1303             Call this method after creation if you prefer long startup times but faster searches.
1304              
1305             =head2 full_graph
1306              
1307             This returns the complete L<Graph> object created from parsing the map.
1308              
1309             =head1 SOURCE
1310              
1311             L<https://github.com/Csson/p5-Map-Metro>
1312              
1313             =head1 HOMEPAGE
1314              
1315             L<https://metacpan.org/release/Map-Metro>
1316              
1317             =head1 AUTHOR
1318              
1319             Erik Carlsson <info@code301.com>
1320              
1321             =head1 COPYRIGHT AND LICENSE
1322              
1323             This software is copyright (c) 2016 by Erik Carlsson.
1324              
1325             This is free software; you can redistribute it and/or modify it under
1326             the same terms as the Perl 5 programming language system itself.
1327              
1328             =cut