line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Travel::Status::DE::HAFAS::Journey; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# vim:foldmethod=marker |
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
8
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
33
|
|
6
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
21
|
|
7
|
1
|
|
|
1
|
|
15
|
use 5.014; |
|
1
|
|
|
|
|
15
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
7
|
no if $] >= 5.018, warnings => 'experimental::smartmatch'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
9
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
98
|
use parent 'Class::Accessor'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
12
|
1
|
|
|
1
|
|
80
|
use DateTime::Format::Strptime; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
17
|
|
13
|
1
|
|
|
1
|
|
58
|
use List::Util qw(any); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
92
|
|
14
|
1
|
|
|
1
|
|
478
|
use Travel::Status::DE::HAFAS::Stop; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
6
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = '4.15'; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Travel::Status::DE::HAFAS::Journey->mk_ro_accessors( |
19
|
|
|
|
|
|
|
qw(datetime sched_datetime rt_datetime |
20
|
|
|
|
|
|
|
is_cancelled is_partially_cancelled |
21
|
|
|
|
|
|
|
station station_eva platform sched_platform rt_platform operator |
22
|
|
|
|
|
|
|
id name type type_long class number line line_no load delay |
23
|
|
|
|
|
|
|
route_end route_start origin destination direction) |
24
|
|
|
|
|
|
|
); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# {{{ Constructor |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub new { |
29
|
30
|
|
|
30
|
1
|
119
|
my ( $obj, %opt ) = @_; |
30
|
|
|
|
|
|
|
|
31
|
30
|
|
50
|
|
|
53
|
my @locL = @{ $opt{common}{locL} // [] }; |
|
30
|
|
|
|
|
214
|
|
32
|
30
|
|
50
|
|
|
53
|
my @prodL = @{ $opt{common}{prodL} // [] }; |
|
30
|
|
|
|
|
104
|
|
33
|
30
|
|
50
|
|
|
55
|
my @opL = @{ $opt{common}{opL} // [] }; |
|
30
|
|
|
|
|
72
|
|
34
|
30
|
|
50
|
|
|
49
|
my @icoL = @{ $opt{common}{icoL} // [] }; |
|
30
|
|
|
|
|
82
|
|
35
|
30
|
|
50
|
|
|
50
|
my @tcocL = @{ $opt{common}{tcocL} // [] }; |
|
30
|
|
|
|
|
102
|
|
36
|
30
|
|
50
|
|
|
53
|
my @remL = @{ $opt{common}{remL} // [] }; |
|
30
|
|
|
|
|
71
|
|
37
|
30
|
|
50
|
|
|
45
|
my @himL = @{ $opt{common}{himL} // [] }; |
|
30
|
|
|
|
|
93
|
|
38
|
|
|
|
|
|
|
|
39
|
30
|
|
|
|
|
67
|
my $hafas = $opt{hafas}; |
40
|
30
|
|
|
|
|
51
|
my $journey = $opt{journey}; |
41
|
|
|
|
|
|
|
|
42
|
30
|
|
|
|
|
112
|
my $date = $journey->{date}; |
43
|
|
|
|
|
|
|
|
44
|
30
|
|
|
|
|
90
|
my $direction = $journey->{dirTxt}; |
45
|
30
|
|
|
|
|
61
|
my $jid = $journey->{jid}; |
46
|
|
|
|
|
|
|
|
47
|
30
|
|
|
|
|
44
|
my $is_cancelled = $journey->{isCncl}; |
48
|
30
|
|
|
|
|
52
|
my $partially_cancelled = $journey->{isPartCncl}; |
49
|
|
|
|
|
|
|
|
50
|
30
|
|
|
|
|
57
|
my $product = $prodL[ $journey->{prodX} ]; |
51
|
30
|
|
33
|
|
|
127
|
my $name = $product->{addName} // $product->{name}; |
52
|
30
|
|
|
|
|
113
|
my $line_no = $product->{prodCtx}{line}; |
53
|
30
|
|
|
|
|
65
|
my $train_no = $product->{prodCtx}{num}; |
54
|
30
|
|
|
|
|
53
|
my $cat = $product->{prodCtx}{catOut}; |
55
|
30
|
|
|
|
|
53
|
my $catlong = $product->{prodCtx}{catOutL}; |
56
|
30
|
50
|
33
|
|
|
152
|
if ( $name and $cat and $name eq $cat ) { |
|
|
|
33
|
|
|
|
|
57
|
0
|
|
|
|
|
0
|
$name .= ' ' . $product->{nameS}; |
58
|
|
|
|
|
|
|
} |
59
|
30
|
50
|
33
|
|
|
105
|
if ( defined $train_no and not $train_no ) { |
60
|
0
|
|
|
|
|
0
|
$train_no = undef; |
61
|
|
|
|
|
|
|
} |
62
|
30
|
0
|
33
|
|
|
71
|
if ( |
|
|
|
0
|
|
|
|
|
|
|
|
33
|
|
|
|
|
63
|
|
|
|
|
|
|
not defined $line_no |
64
|
|
|
|
|
|
|
and defined $product->{prodCtx}{matchId} |
65
|
|
|
|
|
|
|
and |
66
|
|
|
|
|
|
|
( not defined $train_no or $product->{prodCtx}{matchId} ne $train_no ) |
67
|
|
|
|
|
|
|
) |
68
|
|
|
|
|
|
|
{ |
69
|
0
|
|
|
|
|
0
|
$line_no = $product->{prodCtx}{matchId}; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
30
|
|
|
|
|
46
|
my $operator; |
73
|
30
|
50
|
|
|
|
66
|
if ( defined $product->{oprX} ) { |
74
|
30
|
50
|
|
|
|
77
|
if ( my $opref = $opL[ $product->{oprX} ] ) { |
75
|
30
|
|
|
|
|
59
|
$operator = $opref->{name}; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
30
|
|
|
|
|
47
|
my @messages; |
80
|
30
|
|
100
|
|
|
77
|
for my $msg ( @{ $journey->{msgL} // [] } ) { |
|
30
|
|
|
|
|
121
|
|
81
|
1
|
50
|
33
|
|
|
8
|
if ( $msg->{type} eq 'REM' and defined $msg->{remX} ) { |
|
|
0
|
0
|
|
|
|
|
82
|
1
|
|
|
|
|
8
|
push( @messages, $hafas->add_message( $remL[ $msg->{remX} ] ) ); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
elsif ( $msg->{type} eq 'HIM' and defined $msg->{himX} ) { |
85
|
0
|
|
|
|
|
0
|
push( @messages, $hafas->add_message( $himL[ $msg->{himX} ], 1 ) ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
else { |
88
|
0
|
|
|
|
|
0
|
say "Unknown message type $msg->{type}"; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
30
|
|
|
|
|
250
|
my $date_ref = ( split( qr{[|]}, $jid ) )[4]; |
93
|
30
|
|
|
|
|
149
|
my $datetime_ref = DateTime::Format::Strptime->new( |
94
|
|
|
|
|
|
|
pattern => '%d%m%Y', |
95
|
|
|
|
|
|
|
time_zone => 'Europe/Berlin' |
96
|
|
|
|
|
|
|
)->parse_datetime($date_ref); |
97
|
|
|
|
|
|
|
|
98
|
30
|
|
|
|
|
77505
|
my $class = $product->{cls}; |
99
|
|
|
|
|
|
|
|
100
|
30
|
|
|
|
|
72
|
my @stops; |
101
|
|
|
|
|
|
|
my $route_end; |
102
|
30
|
|
50
|
|
|
54
|
for my $stop ( @{ $journey->{stopL} // [] } ) { |
|
30
|
|
|
|
|
170
|
|
103
|
389
|
|
|
|
|
926
|
my $loc = $locL[ $stop->{locX} ]; |
104
|
389
|
|
|
|
|
947
|
my $sched_arr = $stop->{aTimeS}; |
105
|
389
|
|
|
|
|
644
|
my $rt_arr = $stop->{aTimeR}; |
106
|
389
|
|
|
|
|
660
|
my $sched_dep = $stop->{dTimeS}; |
107
|
389
|
|
|
|
|
717
|
my $rt_dep = $stop->{dTimeR}; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# dIn. / aOut. -> may passengers enter / exit the train? |
110
|
|
|
|
|
|
|
|
111
|
389
|
|
66
|
|
|
1120
|
my $sched_platform = $stop->{aPlatfS} // $stop->{dPlatfS}; |
112
|
389
|
|
33
|
|
|
1062
|
my $rt_platform = $stop->{aPlatfR} // $stop->{dPlatfR}; |
113
|
389
|
|
33
|
|
|
1058
|
my $changed_platform = $stop->{aPlatfCh} // $stop->{dPlatfCh}; |
114
|
|
|
|
|
|
|
|
115
|
389
|
|
|
|
|
765
|
for my $timestr ( $sched_arr, $rt_arr, $sched_dep, $rt_dep ) { |
116
|
1556
|
100
|
|
|
|
3235
|
if ( not defined $timestr ) { |
117
|
1138
|
|
|
|
|
1971
|
next; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$timestr = handle_day_change( |
121
|
|
|
|
|
|
|
input => $timestr, |
122
|
|
|
|
|
|
|
date => $date, |
123
|
|
|
|
|
|
|
strp_obj => $hafas->{strptime_obj}, |
124
|
418
|
|
|
|
|
1055
|
ref => $datetime_ref |
125
|
|
|
|
|
|
|
); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
389
|
50
|
66
|
|
|
1110
|
my $arr_delay |
130
|
|
|
|
|
|
|
= ( $sched_arr and $rt_arr ) |
131
|
|
|
|
|
|
|
? ( $rt_arr->epoch - $sched_arr->epoch ) / 60 |
132
|
|
|
|
|
|
|
: undef; |
133
|
|
|
|
|
|
|
|
134
|
389
|
100
|
100
|
|
|
3288
|
my $dep_delay |
135
|
|
|
|
|
|
|
= ( $sched_dep and $rt_dep ) |
136
|
|
|
|
|
|
|
? ( $rt_dep->epoch - $sched_dep->epoch ) / 60 |
137
|
|
|
|
|
|
|
: undef; |
138
|
|
|
|
|
|
|
|
139
|
389
|
|
|
|
|
1391
|
my $arr_cancelled = $stop->{aCncl}; |
140
|
389
|
|
|
|
|
637
|
my $dep_cancelled = $stop->{dCncl}; |
141
|
|
|
|
|
|
|
|
142
|
389
|
|
|
|
|
687
|
my $tco = {}; |
143
|
389
|
|
50
|
|
|
648
|
for my $tco_id ( @{ $stop->{dTrnCmpSX}{tcocX} // [] } ) { |
|
389
|
|
|
|
|
1918
|
|
144
|
0
|
|
|
|
|
0
|
my $tco_kv = $tcocL[$tco_id]; |
145
|
0
|
|
|
|
|
0
|
$tco->{ $tco_kv->{c} } = $tco_kv->{r}; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
push( |
149
|
|
|
|
|
|
|
@stops, |
150
|
|
|
|
|
|
|
{ |
151
|
|
|
|
|
|
|
loc => $loc, |
152
|
|
|
|
|
|
|
extra => { |
153
|
|
|
|
|
|
|
sched_arr => $sched_arr, |
154
|
|
|
|
|
|
|
rt_arr => $rt_arr, |
155
|
|
|
|
|
|
|
arr => $rt_arr // $sched_arr, |
156
|
|
|
|
|
|
|
arr_delay => $arr_delay, |
157
|
|
|
|
|
|
|
arr_cancelled => $arr_cancelled, |
158
|
|
|
|
|
|
|
sched_dep => $sched_dep, |
159
|
|
|
|
|
|
|
rt_dep => $rt_dep, |
160
|
|
|
|
|
|
|
dep => $rt_dep // $sched_dep, |
161
|
|
|
|
|
|
|
dep_delay => $dep_delay, |
162
|
|
|
|
|
|
|
dep_cancelled => $dep_cancelled, |
163
|
|
|
|
|
|
|
delay => $dep_delay // $arr_delay, |
164
|
|
|
|
|
|
|
direction => $stop->{dDirTxt}, |
165
|
389
|
|
66
|
|
|
1395
|
sched_platform => $sched_platform, |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
166
|
|
|
|
|
|
|
rt_platform => $rt_platform, |
167
|
|
|
|
|
|
|
is_changed_platform => $changed_platform, |
168
|
|
|
|
|
|
|
platform => $rt_platform // $sched_platform, |
169
|
|
|
|
|
|
|
load => $tco, |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
); |
173
|
389
|
|
|
|
|
7120
|
$route_end = $loc->{name}; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
30
|
50
|
|
|
|
102
|
if ( $journey->{stbStop} ) { |
177
|
30
|
50
|
|
|
|
73
|
if ( $hafas->{arrivals} ) { |
178
|
0
|
|
|
|
|
0
|
$route_end = $stops[0]->{name}; |
179
|
0
|
|
|
|
|
0
|
pop(@stops); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
else { |
182
|
30
|
|
|
|
|
56
|
shift(@stops); |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
30
|
|
33
|
|
|
492
|
my $ref = { |
187
|
|
|
|
|
|
|
id => $jid, |
188
|
|
|
|
|
|
|
name => $name, |
189
|
|
|
|
|
|
|
number => $train_no, |
190
|
|
|
|
|
|
|
line => $name, |
191
|
|
|
|
|
|
|
line_no => $line_no, |
192
|
|
|
|
|
|
|
type => $cat, |
193
|
|
|
|
|
|
|
type_long => $catlong, |
194
|
|
|
|
|
|
|
class => $class, |
195
|
|
|
|
|
|
|
operator => $operator, |
196
|
|
|
|
|
|
|
direction => $direction, |
197
|
|
|
|
|
|
|
is_cancelled => $is_cancelled, |
198
|
|
|
|
|
|
|
is_partially_cancelled => $partially_cancelled, |
199
|
|
|
|
|
|
|
route_end => $route_end // $direction, |
200
|
|
|
|
|
|
|
messages => \@messages, |
201
|
|
|
|
|
|
|
route => \@stops, |
202
|
|
|
|
|
|
|
}; |
203
|
|
|
|
|
|
|
|
204
|
30
|
50
|
|
|
|
97
|
if ( $journey->{stbStop} ) { |
205
|
30
|
50
|
|
|
|
68
|
if ( $hafas->{arrivals} ) { |
206
|
0
|
|
|
|
|
0
|
$ref->{origin} = $ref->{route_end}; |
207
|
0
|
|
0
|
|
|
0
|
$ref->{is_cancelled} ||= $journey->{stbStop}{aCncl}; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
else { |
210
|
30
|
|
|
|
|
94
|
$ref->{destination} = $ref->{route_end}; |
211
|
30
|
|
66
|
|
|
151
|
$ref->{is_cancelled} ||= $journey->{stbStop}{dCncl}; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
else { |
215
|
0
|
|
|
|
|
0
|
$ref->{route_start} = $stops[0]{name}; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
30
|
|
|
|
|
76
|
bless( $ref, $obj ); |
219
|
|
|
|
|
|
|
|
220
|
30
|
50
|
|
|
|
74
|
if ( $journey->{stbStop} ) { |
221
|
30
|
|
|
|
|
94
|
$ref->{station} = $locL[ $journey->{stbStop}{locX} ]->{name}; |
222
|
30
|
|
|
|
|
78
|
$ref->{station_eva} = 0 + $locL[ $journey->{stbStop}{locX} ]->{extId}; |
223
|
30
|
|
|
|
|
66
|
$ref->{sched_platform} = $journey->{stbStop}{dPlatfS}; |
224
|
30
|
|
|
|
|
64
|
$ref->{rt_platform} = $journey->{stbStop}{dPlatfR}; |
225
|
30
|
|
66
|
|
|
103
|
$ref->{platform} = $ref->{rt_platform} // $ref->{sched_platform}; |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
my $time_s |
228
|
30
|
50
|
|
|
|
134
|
= $journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeS' : 'dTimeS' }; |
229
|
|
|
|
|
|
|
my $time_r |
230
|
30
|
50
|
|
|
|
71
|
= $journey->{stbStop}{ $hafas->{arrivals} ? 'aTimeR' : 'dTimeR' }; |
231
|
|
|
|
|
|
|
|
232
|
30
|
|
|
|
|
66
|
for my $timestr ( $time_s, $time_r ) { |
233
|
60
|
100
|
|
|
|
501
|
if ( not defined $timestr ) { |
234
|
1
|
|
|
|
|
4
|
next; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
$timestr = handle_day_change( |
238
|
|
|
|
|
|
|
input => $timestr, |
239
|
|
|
|
|
|
|
date => $date, |
240
|
|
|
|
|
|
|
strp_obj => $hafas->{strptime_obj}, |
241
|
59
|
|
|
|
|
161
|
ref => $datetime_ref, |
242
|
|
|
|
|
|
|
); |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
30
|
|
|
|
|
59
|
my $datetime_s = $time_s; |
247
|
30
|
|
|
|
|
54
|
my $datetime_r = $time_r; |
248
|
|
|
|
|
|
|
|
249
|
30
|
100
|
|
|
|
88
|
my $delay |
250
|
|
|
|
|
|
|
= $datetime_r |
251
|
|
|
|
|
|
|
? ( $datetime_r->epoch - $datetime_s->epoch ) / 60 |
252
|
|
|
|
|
|
|
: undef; |
253
|
|
|
|
|
|
|
|
254
|
30
|
|
|
|
|
516
|
$ref->{sched_datetime} = $datetime_s; |
255
|
30
|
|
|
|
|
59
|
$ref->{rt_datetime} = $datetime_r; |
256
|
30
|
|
66
|
|
|
76
|
$ref->{datetime} = $datetime_r // $datetime_s; |
257
|
30
|
|
|
|
|
148
|
$ref->{delay} = $delay; |
258
|
|
|
|
|
|
|
|
259
|
30
|
100
|
|
|
|
68
|
if ( $ref->{delay} ) { |
260
|
2
|
|
|
|
|
6
|
$ref->{datetime} = $ref->{rt_datetime}; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
else { |
263
|
28
|
|
|
|
|
53
|
$ref->{datetime} = $ref->{sched_datetime}; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
30
|
|
|
|
|
46
|
my %tco; |
267
|
30
|
|
50
|
|
|
51
|
for my $tco_id ( @{ $journey->{stbStop}{dTrnCmpSX}{tcocX} // [] } ) { |
|
30
|
|
|
|
|
177
|
|
268
|
0
|
|
|
|
|
0
|
my $tco_kv = $tcocL[$tco_id]; |
269
|
0
|
|
|
|
|
0
|
$tco{ $tco_kv->{c} } = $tco_kv->{r}; |
270
|
|
|
|
|
|
|
} |
271
|
30
|
50
|
|
|
|
97
|
if (%tco) { |
272
|
0
|
|
|
|
|
0
|
$ref->{load} = \%tco; |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
} |
275
|
30
|
50
|
|
|
|
68
|
if ( $opt{polyline} ) { |
276
|
0
|
|
|
|
|
0
|
$ref->{polyline} = $opt{polyline}; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
30
|
|
|
|
|
369
|
return $ref; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# }}} |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub handle_day_change { |
285
|
477
|
|
|
477
|
0
|
1604
|
my (%opt) = @_; |
286
|
477
|
|
|
|
|
861
|
my $date = $opt{date}; |
287
|
477
|
|
|
|
|
769
|
my $timestr = $opt{input}; |
288
|
477
|
50
|
|
|
|
1154
|
if ( length($timestr) == 8 ) { |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# arrival time includes a day offset |
291
|
0
|
|
|
|
|
0
|
my $offset_date = $opt{ref}->clone; |
292
|
0
|
|
|
|
|
0
|
$offset_date->add( days => substr( $timestr, 0, 2, q{} ) ); |
293
|
0
|
|
|
|
|
0
|
$offset_date = $offset_date->strftime('%Y%m%d'); |
294
|
0
|
|
|
|
|
0
|
$timestr = $opt{strp_obj}->parse_datetime("${offset_date}T${timestr}"); |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
else { |
297
|
477
|
|
|
|
|
1934
|
$timestr = $opt{strp_obj}->parse_datetime("${date}T${timestr}"); |
298
|
|
|
|
|
|
|
} |
299
|
477
|
|
|
|
|
403525
|
return $timestr; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# {{{ Accessors |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# Legacy |
305
|
|
|
|
|
|
|
sub station_uic { |
306
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
307
|
0
|
|
|
|
|
0
|
return $self->{station_eva}; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub is_changed_platform { |
311
|
3
|
|
|
3
|
1
|
20515
|
my ($self) = @_; |
312
|
|
|
|
|
|
|
|
313
|
3
|
50
|
33
|
|
|
15
|
if ( defined $self->{rt_platform} and defined $self->{sched_platform} ) { |
314
|
0
|
0
|
|
|
|
0
|
if ( $self->{rt_platform} ne $self->{sched_platform} ) { |
315
|
0
|
|
|
|
|
0
|
return 1; |
316
|
|
|
|
|
|
|
} |
317
|
0
|
|
|
|
|
0
|
return 0; |
318
|
|
|
|
|
|
|
} |
319
|
3
|
50
|
|
|
|
10
|
if ( defined $self->{rt_platform} ) { |
320
|
0
|
|
|
|
|
0
|
return 1; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
3
|
|
|
|
|
16
|
return 0; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
sub messages { |
327
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
328
|
|
|
|
|
|
|
|
329
|
0
|
0
|
|
|
|
|
if ( $self->{messages} ) { |
330
|
0
|
|
|
|
|
|
return @{ $self->{messages} }; |
|
0
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
} |
332
|
0
|
|
|
|
|
|
return; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub polyline { |
336
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
337
|
|
|
|
|
|
|
|
338
|
0
|
0
|
|
|
|
|
if ( $self->{polyline} ) { |
339
|
0
|
|
|
|
|
|
return @{ $self->{polyline} }; |
|
0
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
} |
341
|
0
|
|
|
|
|
|
return; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub route { |
345
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
346
|
|
|
|
|
|
|
|
347
|
0
|
0
|
|
|
|
|
if ( $self->{route} ) { |
348
|
0
|
0
|
0
|
|
|
|
if ( $self->{route}[0] and $self->{route}[0]{extra} ) { |
349
|
|
|
|
|
|
|
$self->{route} |
350
|
0
|
|
|
|
|
|
= [ map { Travel::Status::DE::HAFAS::Stop->new( %{$_} ) } |
|
0
|
|
|
|
|
|
|
351
|
0
|
|
|
|
|
|
@{ $self->{route} } ]; |
|
0
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
} |
353
|
0
|
|
|
|
|
|
return @{ $self->{route} }; |
|
0
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
} |
355
|
0
|
|
|
|
|
|
return; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub route_interesting { |
359
|
0
|
|
|
0
|
1
|
|
my ( $self, $max_parts ) = @_; |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
my @via = $self->route; |
362
|
0
|
|
|
|
|
|
my ( @via_main, @via_show, $last_stop ); |
363
|
0
|
|
0
|
|
|
|
$max_parts //= 3; |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# Centraal: dutch main station (Hbf in .nl) |
366
|
|
|
|
|
|
|
# HB: swiss main station (Hbf in .ch) |
367
|
|
|
|
|
|
|
# hl.n.: czech main station (Hbf in .cz) |
368
|
0
|
|
|
|
|
|
for my $stop (@via) { |
369
|
0
|
0
|
|
|
|
|
if ( $stop->{name} |
370
|
|
|
|
|
|
|
=~ m{ HB $ | hl\.n\. $ | Hbf | Hauptbahnhof | Bf | Bahnhof | Centraal | Flughafen }x |
371
|
|
|
|
|
|
|
) |
372
|
|
|
|
|
|
|
{ |
373
|
0
|
|
|
|
|
|
push( @via_main, $stop ); |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
} |
376
|
0
|
|
|
|
|
|
$last_stop = pop(@via); |
377
|
|
|
|
|
|
|
|
378
|
0
|
0
|
0
|
|
|
|
if ( @via_main and $via_main[-1]{name} eq $last_stop->{name} ) { |
379
|
0
|
|
|
|
|
|
pop(@via_main); |
380
|
|
|
|
|
|
|
} |
381
|
0
|
0
|
0
|
|
|
|
if ( @via and $via[-1]{name} eq $last_stop->{name} ) { |
382
|
0
|
|
|
|
|
|
pop(@via); |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
0
|
0
|
0
|
|
|
|
if ( @via_main and @via and $via[0]{name} eq $via_main[0]{name} ) { |
|
|
|
0
|
|
|
|
|
386
|
0
|
|
|
|
|
|
shift(@via_main); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
|
if ( @via < $max_parts ) { |
390
|
0
|
|
|
|
|
|
@via_show = @via; |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
else { |
393
|
0
|
0
|
|
|
|
|
if ( @via_main >= $max_parts ) { |
394
|
0
|
|
|
|
|
|
@via_show = ( $via[0] ); |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
else { |
397
|
0
|
|
|
|
|
|
@via_show = splice( @via, 0, $max_parts - @via_main ); |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
0
|
|
0
|
|
|
|
while ( @via_show < $max_parts and @via_main ) { |
401
|
0
|
|
|
|
|
|
my $stop = shift(@via_main); |
402
|
0
|
0
|
0
|
0
|
|
|
if ( any { $_->{name} eq $stop->{name} } @via_show |
|
0
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
or $stop->{name} eq $last_stop->{name} ) |
404
|
|
|
|
|
|
|
{ |
405
|
0
|
|
|
|
|
|
next; |
406
|
|
|
|
|
|
|
} |
407
|
0
|
|
|
|
|
|
push( @via_show, $stop ); |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
0
|
|
|
|
|
|
for my $stop (@via_show) { |
412
|
0
|
|
|
|
|
|
$stop->{name} =~ s{ \s? Hbf .* }{}x; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
0
|
|
|
|
|
|
return @via_show; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub TO_JSON { |
420
|
0
|
|
|
0
|
0
|
|
my ($self) = @_; |
421
|
|
|
|
|
|
|
|
422
|
0
|
|
|
|
|
|
my $ret = { %{$self} }; |
|
0
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
|
424
|
0
|
|
|
|
|
|
for my $k ( keys %{$ret} ) { |
|
0
|
|
|
|
|
|
|
425
|
0
|
0
|
|
|
|
|
if ( ref( $ret->{$k} ) eq 'DateTime' ) { |
426
|
0
|
|
|
|
|
|
$ret->{$k} = $ret->{$k}->epoch; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} |
429
|
0
|
|
|
|
|
|
$ret->{route} = [ map { $_->TO_JSON } $self->route ]; |
|
0
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
|
431
|
0
|
|
|
|
|
|
return $ret; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# }}} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
1; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
__END__ |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=head1 NAME |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
Travel::Status::DE::HAFAS::Journey - Information about a single |
443
|
|
|
|
|
|
|
journey received by Travel::Status::DE::HAFAS |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=head1 SYNOPSIS |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
for my $departure ($status->results) { |
448
|
|
|
|
|
|
|
printf( |
449
|
|
|
|
|
|
|
"At %s: %s to %s from platform %s\n", |
450
|
|
|
|
|
|
|
$departure->datetime->strftime('%H:%M'), |
451
|
|
|
|
|
|
|
$departure->line, |
452
|
|
|
|
|
|
|
$departure->destination, |
453
|
|
|
|
|
|
|
$departure->platform, |
454
|
|
|
|
|
|
|
); |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
# or (depending on module setup) |
458
|
|
|
|
|
|
|
for my $arrival ($status->results) { |
459
|
|
|
|
|
|
|
printf( |
460
|
|
|
|
|
|
|
"At %s: %s from %s on platform %s\n", |
461
|
|
|
|
|
|
|
$arrival->datetime->strftime('%H:%M'), |
462
|
|
|
|
|
|
|
$arrival->line, |
463
|
|
|
|
|
|
|
$arrival->origin, |
464
|
|
|
|
|
|
|
$arrival->platform, |
465
|
|
|
|
|
|
|
); |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
=head1 VERSION |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
version 4.15 |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
=head1 DESCRIPTION |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
Travel::Status::DE::HAFAS::Journey describes a single journey. It is either |
475
|
|
|
|
|
|
|
a station-specific arrival/departure obtained by a stationboard query, or a |
476
|
|
|
|
|
|
|
train journey that does not belong to a specific station. |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
stationboard-specific accessors are annotated with "(station only)" and return |
479
|
|
|
|
|
|
|
undef for non-station journeys. |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=head1 METHODS |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
=head2 ACCESSORS |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=over |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=item $journey->name |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
Returns the journey or line name, either in a format like "Bus SB16" (Bus line |
490
|
|
|
|
|
|
|
SB16) or "RE 10111" (RegionalExpress train 10111, no line information). May |
491
|
|
|
|
|
|
|
contain extraneous whitespace characters. |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=item $journey->type |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
Returns the type of this journey, e.g. "S" for S-Bahn, "RE" for Regional Express |
496
|
|
|
|
|
|
|
or "STR" for tram / StraE<szlig>enbahn. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=item $journey->type_long |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Returns the long type of this journey, e.g. "S-Bahn" or "Regional-Express". |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=item $journey->class |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
Returns an integer identifying the the mode of transport class. |
505
|
|
|
|
|
|
|
Semantics depend on backend, e.g. "1" and "2" for long-distance trains and |
506
|
|
|
|
|
|
|
"4" and "8" for regional trains. |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
=item $journey->line |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
Returns the journey or line name, either in a format like "Bus SB16" (Bus line |
511
|
|
|
|
|
|
|
SB16), "RE 42" (RegionalExpress train 42) or "IC 2901" (InterCity train 2901, |
512
|
|
|
|
|
|
|
no line information). May contain extraneous whitespace characters. Note that |
513
|
|
|
|
|
|
|
this accessor does not return line informatikn for IC/ICE/EC services, even if |
514
|
|
|
|
|
|
|
it is available. Use B<line_no> for those. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item $journey->line_no |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
Returns the line identifier, or undef if it is unknown. |
519
|
|
|
|
|
|
|
The line identifier may be a single number such as "11" (underground train |
520
|
|
|
|
|
|
|
line U 11), a single word (e.g. "AIR") or a combination (e.g. "SB16"). |
521
|
|
|
|
|
|
|
May also provide line numbers of IC/ICE services. |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=item $journey->number |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
Returns the journey number (e.g. train number), or undef if it is unknown. |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=item $journey->id |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
Returns tha HAFAS-internal journey ID. |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=item $journey->rt_datetime (station only) |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
DateTime object indicating the actual arrival/departure date and time. |
534
|
|
|
|
|
|
|
undef if no real-time data is available. |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=item $journey->sched_datetime (station only) |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
DateTime object indicating the scheduled arrival/departure date and time. |
539
|
|
|
|
|
|
|
undef if no schedule data is available. |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=item $journey->datetime (station only) |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
DateTime object indicating the arrival/departure date and time. |
544
|
|
|
|
|
|
|
Real-time data if available, schedule data otherwise. |
545
|
|
|
|
|
|
|
undef if neither is available. |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
=item $journey->delay (station only) |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
Returns the delay in minutes, or undef if it is unknown. |
550
|
|
|
|
|
|
|
Also returns undef if the arrival/departure has been cancelled. |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=item $journey->is_cancelled |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
True if the journey was cancelled, false otherwise. |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=item $journey->is_partially_cancelled |
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
True if part of the journey was cancelled, false otherwise. |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
=item $journey->rt_platform (station only) |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
Actual arrival/departure platform. |
563
|
|
|
|
|
|
|
undef if no real-time data is available. |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
=item $journey->sched_platform (station only) |
566
|
|
|
|
|
|
|
|
567
|
|
|
|
|
|
|
Scheduled arrival/departure platform. |
568
|
|
|
|
|
|
|
undef if no scheduled platform is available. |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=item $journey->platform (station only) |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
Arrival/Departure platform. Real-time data if available, schedule data |
573
|
|
|
|
|
|
|
otherwise. May be undef. |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=item $journey->is_changed_platform (station only) |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
True if the real-time platform is known and it is not the scheduled one. |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
=item $journey->load (station only) |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
Expected passenger load (i.e., how full the vehicle is) at the requested stop. |
582
|
|
|
|
|
|
|
If known, returns a hashref that maps classes (typically FIRST/SECOND) to |
583
|
|
|
|
|
|
|
load estimation numbers. The DB backend uses 1 (low to medium), 2 (high), |
584
|
|
|
|
|
|
|
3 (very high), and 4 (exceptionally high, train is booked out). |
585
|
|
|
|
|
|
|
Undef if unknown. |
586
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
=item $journey->messages |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
Returns a list of message strings related to this journey. Messages usually are |
590
|
|
|
|
|
|
|
service notices (e.g. "missing carriage") or detailed delay reasons |
591
|
|
|
|
|
|
|
(e.g. "switch damage between X and Y, expect delays"). |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
=item $journey->operator |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
Returns the operator responsible for this journey. Returns undef |
596
|
|
|
|
|
|
|
if the backend does not provide an operator. |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=item $journey->station (station only) |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Name of the station at which this journey was requested. |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
=item $journey->station_eva (station only) |
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
UIC/EVA ID of the station at which this journey was requested. |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
=item $journey->route |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
Returns a list of Travel::Status::DE::HAFAS::Stop(3pm) objects that describe |
609
|
|
|
|
|
|
|
individual stops along the journey. In stationboard mode, the list only |
610
|
|
|
|
|
|
|
contains arrivals prior to the requested station or departures after the |
611
|
|
|
|
|
|
|
requested station. In journey mode, it contains the entire route. |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
=item $journey->route_interesting([I<count>]) |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
Return up to I<count> (default: B<3>) parts of C<< $journey->route >> that may |
616
|
|
|
|
|
|
|
be particularly helpful, e.g. main stations or airports. |
617
|
|
|
|
|
|
|
Returns a list of hashes, see above for the layout. |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
=item $journey->route_end |
620
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
Name of the last route station. In arrival mode, this is where the train |
622
|
|
|
|
|
|
|
started; in all other cases, it is the terminus. |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
=item $journey->destination |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
Alias for route_end; only set when requesting departures in station mode. |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=item $journey->origin |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
Alias for route_end; only set when requesting arrivals in station mode. |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
=item $journey->direction |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
Train direction; this is typically the text printed on the train itself. |
635
|
|
|
|
|
|
|
May be different from destination / route_end and may change along the route, |
636
|
|
|
|
|
|
|
see above. |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
=item $journey->polyline (journey only) |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
List of geocoordinates that describe the train's route. Each list entry is |
641
|
|
|
|
|
|
|
a hash with the following keys. |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
=over |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=item * lon (longitude) |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
=item * lat (latitude) |
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
=item * name (name of stop at this location, if any. undef otherwise) |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
=item * eva (EVA ID of stop at this location, if any. undef otherwise) |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=back |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
Note that stop locations in B<polyline> may differ from the coordinates |
656
|
|
|
|
|
|
|
returned in B<route>. This is a backend issue; Travel::Status::DE::HAFAS |
657
|
|
|
|
|
|
|
simply passes the returned coordinates on. |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
=back |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
None. |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
=over |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=item Class::Accessor(3pm) |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
=back |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
None known. |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
=head1 SEE ALSO |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
Travel::Status::DE::HAFAS(3pm). |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
=head1 AUTHOR |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
Copyright (C) 2015-2022 by Birte Kristina Friesel E<lt>derf@finalrewind.orgE<gt> |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=head1 LICENSE |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
This module is licensed under the same terms as Perl itself. |