summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2015-04-27 18:14:57 +0200
committerDaniel Friesel <derf@finalrewind.org>2015-04-27 18:14:57 +0200
commit6d8a390dcff71ef1c4b7755dac97c0e1111e5230 (patch)
tree420fd3a425d1e2f4b130cf0b01dfe41a12bfda63
parenta99025f2d9ba31399e38d34ba95427f56866308d (diff)
parse <ref> in fchg, add replacement support to backend and frontend
-rw-r--r--Changelog2
-rwxr-xr-xbin/db-iris52
-rw-r--r--lib/Travel/Status/DE/IRIS.pm41
-rw-r--r--lib/Travel/Status/DE/IRIS/Result.pm58
4 files changed, 128 insertions, 25 deletions
diff --git a/Changelog b/Changelog
index 8fc9ebd..37aa4ea 100644
--- a/Changelog
+++ b/Changelog
@@ -5,6 +5,8 @@ git HEAD
* db-iris: Indicate wings in output
* Result: Remove train_no_transfer accessor (was based on erroneous
assumptions)
+ * Result: Add replaced_by and replacement_for accessors
+ * db-iris: Add -or to show replacement information
Travel::Status::DE::IRIS 0.08 - Thu Mar 12 2015
diff --git a/bin/db-iris b/bin/db-iris
index f2b65b0..91a1d88 100755
--- a/bin/db-iris
+++ b/bin/db-iris
@@ -85,17 +85,18 @@ if ($time) {
for my $efield (@edata_pre) {
given ($efield) {
- when ('a') { $edata{additional} = 1 }
- when ('c') { $edata{canceled} = 1 }
- when ('d') { $edata{delay} = 1 }
- when ('D') { $edata{delays} = 1 }
- when ('f') { $edata{fullroute} = 1 }
- when ('m') { $edata{messages} = 1 }
- when ('q') { $edata{qos} = 1 }
- when ('r') { $edata{route} = 1 }
- when ('t') { $edata{times} = 1 }
- when ('!') { $edata{debug} = 1 }
- default { $edata{$efield} = 1 }
+ when ('a') { $edata{additional} = 1 }
+ when ('c') { $edata{canceled} = 1 }
+ when ('d') { $edata{delay} = 1 }
+ when ('D') { $edata{delays} = 1 }
+ when ('f') { $edata{fullroute} = 1 }
+ when ('m') { $edata{messages} = 1 }
+ when ('q') { $edata{qos} = 1 }
+ when ('r') { $edata{route} = 1 }
+ when ('R') { $edata{replacements} = 1 }
+ when ('t') { $edata{times} = 1 }
+ when ('!') { $edata{debug} = 1 }
+ default { $edata{$efield} = 1 }
}
}
@@ -263,6 +264,23 @@ sub display_result {
print "\n";
}
+ if ( $edata{replacements} ) {
+ for my $e ( $d->replaced_by ) {
+ printf(
+ "Ersatzzug: %s%s %s\n",
+ $e->type, $e->line_no // q{},
+ $e->train_no
+ );
+ }
+ for my $e ( $d->replacement_for ) {
+ printf(
+ "Ersatzzug für: %s%s %s\n",
+ $e->type, $e->line_no // q{},
+ $e->train_no
+ );
+ }
+ }
+
if ( $edata{additional} and $d->additional_stops ) {
printf( "Zusätzlicher Halt in: %s\n",
join( q{, }, $d->additional_stops ) );
@@ -368,9 +386,12 @@ for my $d ( $status->results() ) {
push(
@output,
[
- $timestr, $d->train . ($d->is_unscheduled ? ' !' : q{}),
+ $timestr,
+ $d->train . ( $d->is_unscheduled ? ' !' : q{} ),
$edata{route} ? join( q{ }, $d->route_interesting ) : q{},
- $d->route_end, $platformstr // q{}, $d
+ $d->route_end,
+ $platformstr // q{},
+ $d
]
);
@@ -507,6 +528,11 @@ omitted, use the m / messages type to see those as well.
Show up to three stops between I<station> and the train's destination.
+=item R / replacements
+
+For cancelled trains: Print their replacement train(s), if present.
+For unplanned trains: Print the train(s) they replace, if present.
+
=item t / times
Show both scheduled and expected arrival and departure times.
diff --git a/lib/Travel/Status/DE/IRIS.pm b/lib/Travel/Status/DE/IRIS.pm
index 95194ff..cea7d4a 100644
--- a/lib/Travel/Status/DE/IRIS.pm
+++ b/lib/Travel/Status/DE/IRIS.pm
@@ -101,6 +101,9 @@ sub new {
# references to each other. therefore, they must be processed last.
$self->create_wing_refs;
+ # same goes for replacement refs (the <ref> tag in the fchg document)
+ $self->create_replacement_refs;
+
return $self;
}
@@ -218,12 +221,12 @@ sub get_realtime {
my $station = ( $xml->findnodes('/timetable') )[0]->getAttribute('station');
for my $s ( $xml->findnodes('/timetable/s') ) {
- my $id = $s->getAttribute('id');
- my $e_tl = ( $s->findnodes('./tl') )[0];
- my $e_ar = ( $s->findnodes('./ar') )[0];
- my $e_dp = ( $s->findnodes('./dp') )[0];
- my $e_ref = ( $s->findnodes('./ref') )[0];
- my @e_ms = $s->findnodes('.//m');
+ my $id = $s->getAttribute('id');
+ my $e_tl = ( $s->findnodes('./tl') )[0];
+ my $e_ar = ( $s->findnodes('./ar') )[0];
+ my $e_dp = ( $s->findnodes('./dp') )[0];
+ my @e_refs = $s->findnodes('./ref/tl');
+ my @e_ms = $s->findnodes('.//m');
my %messages;
@@ -268,8 +271,8 @@ sub get_realtime {
unknown_o => $e_tl->getAttribute('o'), # owner: 03/80/R2/...
);
}
- if ($e_ref) {
- $result->set_ref(
+ for my $e_ref (@e_refs) {
+ $result->add_raw_ref(
class => $e_ref->getAttribute('f'), # D N S F
unknown_t => $e_ref->getAttribute('t'), # p
train_no => $e_ref->getAttribute('n'), # dep number
@@ -312,6 +315,14 @@ sub get_result_by_id {
return $res;
}
+sub get_result_by_train {
+ my ( $self, $type, $train_no ) = @_;
+
+ my $res = first { $_->type eq $type and $_->train_no eq $train_no }
+ @{ $self->{results} };
+ return $res;
+}
+
sub create_wing_refs {
my ($self) = @_;
@@ -336,6 +347,20 @@ sub create_wing_refs {
}
+sub create_replacement_refs {
+ my ($self) = @_;
+
+ for my $r ( $self->results ) {
+ for my $ref_hash ( @{ $r->{refs} // [] } ) {
+ my $ref = $self->get_result_by_train( $ref_hash->{type},
+ $ref_hash->{train_no} );
+ if ($ref) {
+ $r->add_reference($ref);
+ }
+ }
+ }
+}
+
sub errstr {
my ($self) = @_;
diff --git a/lib/Travel/Status/DE/IRIS/Result.pm b/lib/Travel/Status/DE/IRIS/Result.pm
index ebcb5be..85ee1bf 100644
--- a/lib/Travel/Status/DE/IRIS/Result.pm
+++ b/lib/Travel/Status/DE/IRIS/Result.pm
@@ -96,8 +96,8 @@ my %translation = (
Travel::Status::DE::IRIS::Result->mk_ro_accessors(
qw(arrival classes date datetime delay departure is_cancelled is_transfer
- is_unscheduled is_wing line_no old_train_id
- old_train_no platform raw_id realtime_xml route_start route_end
+ is_unscheduled is_wing line_no old_train_id old_train_no platform raw_id
+ realtime_xml route_start route_end
sched_arrival sched_departure sched_platform sched_route_start
sched_route_end start stop_no time train_id train_no transfer type
unknown_t unknown_o wing_id)
@@ -309,10 +309,10 @@ sub set_realtime {
return $self;
}
-sub set_ref {
+sub add_raw_ref {
my ( $self, %attrib ) = @_;
- # TODO
+ push( @{ $self->{refs} }, \%attrib );
return $self;
}
@@ -337,6 +337,7 @@ sub add_arrival_wingref {
$ref->{is_wing} = 1;
weaken($ref);
push( @{ $self->{arrival_wings} }, $ref );
+ return $self;
}
sub add_departure_wingref {
@@ -345,6 +346,25 @@ sub add_departure_wingref {
$ref->{is_wing} = 1;
weaken($ref);
push( @{ $self->{departure_wings} }, $ref );
+ return $self;
+}
+
+sub add_reference {
+ my ( $self, $ref ) = @_;
+
+ $ref->add_inverse_reference($self);
+ weaken($ref);
+ push( @{ $self->{replacement_for} }, $ref );
+ return $self;
+}
+
+# never called externally
+sub add_inverse_reference {
+ my ( $self, $ref ) = @_;
+
+ weaken($ref);
+ push( @{ $self->{replaced_by} }, $ref );
+ return $self;
}
# List::Compare does not keep the order of its arguments (even with unsorted).
@@ -476,6 +496,24 @@ sub departure_wings {
return;
}
+sub replaced_by {
+ my ($self) = @_;
+
+ if ( $self->{replaced_by} ) {
+ return @{ $self->{replaced_by} };
+ }
+ return;
+}
+
+sub replacement_for {
+ my ($self) = @_;
+
+ if ( $self->{replacement_for} ) {
+ return @{ $self->{replacement_for} };
+ }
+ return;
+}
+
sub dump_message_codes {
my ($self) = @_;
@@ -912,6 +950,18 @@ available.
This is a developer option. It may be removed without prior warning.
+=item $result->replaced_by
+
+Returns a list of references to Travel::Status::DE::IRIS::Result(3pm) objects
+which replace the (usually cancelled) arrival/departure of this train.
+Returns nothing (false / empty list) otherwise.
+
+=item $result->replacement_for
+
+Returns a list of references to Travel::Status::DE::IRIS::Result(3pm) objects
+which this (usually unplanned) train is meant to replace.
+Returns nothing (false / empty list) otherwise.
+
=item $result->route
List of all stations served by this train, according to its schedule. Does