From 6d8a390dcff71ef1c4b7755dac97c0e1111e5230 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 27 Apr 2015 18:14:57 +0200 Subject: parse in fchg, add replacement support to backend and frontend --- Changelog | 2 ++ bin/db-iris | 52 ++++++++++++++++++++++++--------- lib/Travel/Status/DE/IRIS.pm | 41 +++++++++++++++++++++----- lib/Travel/Status/DE/IRIS/Result.pm | 58 ++++++++++++++++++++++++++++++++++--- 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 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 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 -- cgit v1.2.3