summaryrefslogtreecommitdiff
path: root/lib/Travelynx/Model
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Travelynx/Model')
-rw-r--r--lib/Travelynx/Model/InTransit.pm152
-rwxr-xr-xlib/Travelynx/Model/Journeys.pm245
-rw-r--r--lib/Travelynx/Model/Stations.pm217
-rw-r--r--lib/Travelynx/Model/Traewelling.pm1
-rw-r--r--lib/Travelynx/Model/Users.pm51
5 files changed, 468 insertions, 198 deletions
diff --git a/lib/Travelynx/Model/InTransit.pm b/lib/Travelynx/Model/InTransit.pm
index 69026ac..62e60f1 100644
--- a/lib/Travelynx/Model/InTransit.pm
+++ b/lib/Travelynx/Model/InTransit.pm
@@ -47,6 +47,16 @@ sub epoch_to_dt {
);
}
+sub epoch_or_dt_to_dt {
+ my ($input) = @_;
+
+ if ( ref($input) eq 'DateTime' ) {
+ return $input;
+ }
+
+ return epoch_to_dt($input);
+}
+
sub new {
my ( $class, %opt ) = @_;
@@ -83,11 +93,13 @@ sub add {
my $uid = $opt{uid};
my $db = $opt{db} // $self->{pg}->db;
+ my $backend_id = $opt{backend_id};
my $train = $opt{train};
my $journey = $opt{journey};
my $stop = $opt{stop};
my $checkin_station_id = $opt{departure_eva};
my $route = $opt{route};
+ my $data = $opt{data};
my $json = JSON->new;
@@ -114,9 +126,11 @@ sub add {
data => JSON->new->encode(
{
rt => $train->departure_has_realtime ? 1
- : 0
+ : 0,
+ %{ $data // {} }
}
),
+ backend_id => $backend_id,
}
);
}
@@ -137,7 +151,9 @@ sub add {
rt_dep => _epoch( $j_stop->rt_dep ),
arr_delay => $j_stop->arr_delay,
dep_delay => $j_stop->dep_delay,
- load => $j_stop->load
+ load => $j_stop->load,
+ lat => $j_stop->loc->lat,
+ lon => $j_stop->loc->lon,
}
]
);
@@ -162,7 +178,13 @@ sub add {
sched_departure => $stop->{sched_dep},
real_departure => $stop->{rt_dep} // $stop->{sched_dep},
route => $json->encode( \@route ),
- data => JSON->new->encode( { rt => $stop->{rt_dep} ? 1 : 0 } ),
+ data => JSON->new->encode(
+ {
+ rt => $stop->{rt_dep} ? 1 : 0,
+ %{ $data // {} }
+ }
+ ),
+ backend_id => $backend_id,
}
);
}
@@ -211,8 +233,15 @@ sub postprocess {
if ($is_after) {
push( @route_after, $station );
}
- if ( $ret->{dep_name}
- and $station->[0] eq $ret->{dep_name} )
+
+ # Note that the departure stop may be present more than once in @route,
+ # e.g. when traveling along ring lines such as S41 / S42 in Berlin.
+ if (
+ $ret->{dep_name}
+ and $station->[0] eq $ret->{dep_name}
+ and not($station->[2]{sched_dep}
+ and $station->[2]{sched_dep} < $ret->{sched_dep_ts} )
+ )
{
$is_after = 1;
if ( @{$station} > 1 and not $dep_info ) {
@@ -236,6 +265,11 @@ sub postprocess {
$ret->{extra_data} = $ret->{data};
$ret->{comment} = $ret->{user_data}{comment};
+ $ret->{platform_type} = 'Gleis';
+ if ( $ret->{train_type} =~ m{ ast | bus | ruf }ix ) {
+ $ret->{platform_type} = 'Steig';
+ }
+
$ret->{visibility_str}
= $ret->{visibility}
? $visibility_itoa{ $ret->{visibility} }
@@ -273,31 +307,25 @@ sub postprocess {
# station is present several times in a train's route, e.g.
# for Frankfurt Flughafen in some nightly connections.
my $times = $station->[2] // {};
- if ( $times->{sched_arr}
- and ref( $times->{sched_arr} ) ne 'DateTime' )
- {
- $times->{sched_arr}
- = epoch_to_dt( $times->{sched_arr} );
- if ( $times->{rt_arr} ) {
- $times->{rt_arr}
- = epoch_to_dt( $times->{rt_arr} );
- $times->{arr_delay}
- = $times->{rt_arr}->epoch - $times->{sched_arr}->epoch;
+ for my $key (qw(sched_arr rt_arr sched_dep rt_dep)) {
+ if ( $times->{$key} ) {
+ $times->{$key}
+ = epoch_or_dt_to_dt( $times->{$key} );
}
+ }
+ if ( $times->{sched_arr} and $times->{rt_arr} ) {
+ $times->{arr_delay}
+ = $times->{rt_arr}->epoch - $times->{sched_arr}->epoch;
+ }
+ if ( $times->{sched_arr} or $times->{rt_arr} ) {
$times->{arr} = $times->{rt_arr} || $times->{sched_arr};
$times->{arr_countdown} = $times->{arr}->epoch - $epoch;
}
- if ( $times->{sched_dep}
- and ref( $times->{sched_dep} ) ne 'DateTime' )
- {
- $times->{sched_dep}
- = epoch_to_dt( $times->{sched_dep} );
- if ( $times->{rt_dep} ) {
- $times->{rt_dep}
- = epoch_to_dt( $times->{rt_dep} );
- $times->{dep_delay}
- = $times->{rt_dep}->epoch - $times->{sched_dep}->epoch;
- }
+ if ( $times->{sched_dep} and $times->{rt_dep} ) {
+ $times->{dep_delay}
+ = $times->{rt_dep}->epoch - $times->{sched_dep}->epoch;
+ }
+ if ( $times->{sched_dep} or $times->{rt_dep} ) {
$times->{dep} = $times->{rt_dep} || $times->{sched_dep};
$times->{dep_countdown} = $times->{dep}->epoch - $epoch;
}
@@ -408,17 +436,20 @@ sub get_all_active {
->hashes->each;
}
-sub get_checkout_station_id {
+sub get_checkout_ids {
my ( $self, %opt ) = @_;
my $uid = $opt{uid};
my $db = $opt{db} // $self->{pg}->db;
- my $status = $db->select( 'in_transit', ['checkout_station_id'],
- { user_id => $uid } )->hash;
+ my $status = $db->select(
+ 'in_transit',
+ [ 'checkout_station_id', 'backend_id' ],
+ { user_id => $uid }
+ )->hash;
if ($status) {
- return $status->{checkout_station_id};
+ return $status->{checkout_station_id}, $status->{backend_id};
}
return;
}
@@ -457,13 +488,6 @@ sub set_arrival {
my $uid = $opt{uid};
my $db = $opt{db} // $self->{pg}->db;
my $train = $opt{train};
- my $route = $opt{route};
-
- $route = $self->_merge_old_route(
- db => $db,
- uid => $uid,
- route => $route
- );
my $json = JSON->new;
@@ -474,7 +498,6 @@ sub set_arrival {
arr_platform => $train->platform,
sched_arrival => $train->sched_arrival,
real_arrival => $train->arrival,
- route => $json->encode($route),
messages => $json->encode(
[ map { [ $_->[0]->epoch, $_->[1] ] } $train->messages ]
)
@@ -566,7 +589,8 @@ sub set_polyline {
$self->set_polyline_id(
uid => $uid,
db => $db,
- polyline_id => $polyline_id
+ polyline_id => $polyline_id,
+ train_id => $opt{train_id},
);
}
@@ -579,11 +603,13 @@ sub set_polyline_id {
my $db = $opt{db} // $self->{pg}->db;
my $polyline_id = $opt{polyline_id};
- $db->update(
- 'in_transit',
- { polyline_id => $polyline_id },
- { user_id => $uid }
- );
+ my %where = ( user_id => $uid );
+
+ if ( $opt{train_id} ) {
+ $where{train_id} = $opt{train_id};
+ }
+
+ $db->update( 'in_transit', { polyline_id => $polyline_id }, \%where );
}
sub set_route_data {
@@ -596,6 +622,12 @@ sub set_route_data {
my $qos_msg = $opt{qos_messages};
my $him_msg = $opt{him_messages};
+ my %where = ( user_id => $uid );
+
+ if ( $opt{train_id} ) {
+ $where{train_id} = $opt{train_id};
+ }
+
my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } )
->expand->hash;
@@ -612,7 +644,7 @@ sub set_route_data {
route => JSON->new->encode($route),
data => JSON->new->encode($data)
},
- { user_id => $uid }
+ \%where
);
}
@@ -778,7 +810,6 @@ sub update_arrival_hafas {
my $stop = $opt{stop};
my $json = JSON->new;
- # TODO use old rt data if available
my @route;
for my $j_stop ( $journey->route ) {
push(
@@ -793,7 +824,9 @@ sub update_arrival_hafas {
rt_dep => _epoch( $j_stop->rt_dep ),
arr_delay => $j_stop->arr_delay,
dep_delay => $j_stop->dep_delay,
- load => $j_stop->load
+ load => $j_stop->load,
+ lat => $j_stop->loc->lat,
+ lon => $j_stop->loc->lon,
}
]
);
@@ -839,6 +872,12 @@ sub update_data {
my $db = $opt{db} // $self->{pg}->db;
my $new_data = $opt{data} // {};
+ my %where = ( user_id => $uid );
+
+ if ( $opt{train_id} ) {
+ $where{train_id} = $opt{train_id};
+ }
+
my $res_h = $db->select( 'in_transit', ['data'], { user_id => $uid } )
->expand->hash;
@@ -848,11 +887,7 @@ sub update_data {
$data->{$k} = $v;
}
- $db->update(
- 'in_transit',
- { data => JSON->new->encode($data) },
- { user_id => $uid }
- );
+ $db->update( 'in_transit', { data => JSON->new->encode($data) }, \%where );
}
sub update_user_data {
@@ -862,6 +897,12 @@ sub update_user_data {
my $db = $opt{db} // $self->{pg}->db;
my $new_data = $opt{user_data} // {};
+ my %where = ( user_id => $uid );
+
+ if ( $opt{train_id} ) {
+ $where{train_id} = $opt{train_id};
+ }
+
my $res_h = $db->select( 'in_transit', ['user_data'], { user_id => $uid } )
->expand->hash;
@@ -871,11 +912,8 @@ sub update_user_data {
$data->{$k} = $v;
}
- $db->update(
- 'in_transit',
- { user_data => JSON->new->encode($data) },
- { user_id => $uid }
- );
+ $db->update( 'in_transit',
+ { user_data => JSON->new->encode($data) }, \%where );
}
sub update_visibility {
diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm
index 97c4681..343d680 100755
--- a/lib/Travelynx/Model/Journeys.pm
+++ b/lib/Travelynx/Model/Journeys.pm
@@ -118,8 +118,10 @@ sub add {
my $db = $opt{db};
my $uid = $opt{uid};
my $now = DateTime->now( time_zone => 'Europe/Berlin' );
- my $dep_station = $self->{stations}->search( $opt{dep_station} );
- my $arr_station = $self->{stations}->search( $opt{arr_station} );
+ my $dep_station = $self->{stations}
+ ->search( $opt{dep_station}, backend_id => $opt{backend_id} );
+ my $arr_station = $self->{stations}
+ ->search( $opt{arr_station}, backend_id => $opt{backend_id} );
if ( not $dep_station ) {
return ( undef, 'Unbekannter Startbahnhof' );
@@ -167,16 +169,36 @@ sub add {
my @route;
if ( not $route_has_start ) {
- push( @route, [ $dep_station->{name}, $dep_station->{eva}, {} ] );
+ push(
+ @route,
+ [
+ $dep_station->{name},
+ $dep_station->{eva},
+ {
+ lat => $dep_station->{lat},
+ lon => $dep_station->{lon},
+ }
+ ]
+ );
}
if ( $opt{route} ) {
my @unknown_stations;
for my $station ( @{ $opt{route} } ) {
- my $station_info = $self->{stations}->search($station);
+ my $station_info = $self->{stations}
+ ->search( $station, backend_id => $opt{backend_id} );
if ($station_info) {
- push( @route,
- [ $station_info->{name}, $station_info->{eva}, {} ] );
+ push(
+ @route,
+ [
+ $station_info->{name},
+ $station_info->{eva},
+ {
+ lat => $station_info->{lat},
+ lon => $station_info->{lon},
+ }
+ ]
+ );
}
else {
push( @route, [ $station, undef, {} ] );
@@ -198,7 +220,17 @@ sub add {
}
if ( not $route_has_stop ) {
- push( @route, [ $arr_station->{name}, $arr_station->{eva}, {} ] );
+ push(
+ @route,
+ [
+ $arr_station->{name},
+ $arr_station->{eva},
+ {
+ lat => $arr_station->{lat},
+ lon => $arr_station->{lon},
+ }
+ ]
+ );
}
my $entry = {
@@ -218,6 +250,7 @@ sub add {
edited => 0x3fff,
cancelled => $opt{cancelled} ? 1 : 0,
route => JSON->new->encode( \@route ),
+ backend_id => $opt{backend_id},
};
if ( $opt{comment} ) {
@@ -515,7 +548,7 @@ sub get {
my @select
= (
- qw(journey_id train_type train_line train_no checkin_ts sched_dep_ts real_dep_ts dep_eva dep_ds100 dep_name dep_lat dep_lon checkout_ts sched_arr_ts real_arr_ts arr_eva arr_ds100 arr_name arr_lat arr_lon cancelled edited route messages user_data visibility effective_visibility)
+ qw(journey_id is_iris is_hafas backend_name backend_id train_type train_line train_no checkin_ts sched_dep_ts real_dep_ts dep_eva dep_ds100 dep_name dep_lat dep_lon checkout_ts sched_arr_ts real_arr_ts arr_eva arr_ds100 arr_name arr_lat arr_lon cancelled edited route messages user_data visibility effective_visibility)
);
my %where = (
user_id => $uid,
@@ -573,6 +606,10 @@ sub get {
my $ref = {
id => $entry->{journey_id},
+ is_iris => $entry->{is_iris},
+ is_hafas => $entry->{is_hafas},
+ backend_name => $entry->{backend_name},
+ backend_id => $entry->{backend_id},
type => $entry->{train_type},
line => $entry->{train_line},
no => $entry->{train_no},
@@ -632,7 +669,10 @@ sub get {
my $rename = $self->{renamed_station};
for my $stop ( @{ $ref->{route} } ) {
if ( $stop->[0] =~ m{^Betriebsstelle nicht bekannt (\d+)$} ) {
- if ( my $s = $self->{stations}->get_by_eva($1) ) {
+ if ( my $s
+ = $self->{stations}
+ ->get_by_eva( $1, backend_id => $ref->{backend_id} ) )
+ {
$stop->[0] = $s->{name};
}
}
@@ -767,14 +807,40 @@ sub get_oldest_ts {
return undef;
}
-sub get_latest_checkout_station_id {
+sub get_latest_checkout_latlon {
+ my ( $self, %opt ) = @_;
+ my $uid = $opt{uid};
+ my $db = $opt{db} // $self->{pg}->db;
+
+ my $res_h = $db->select(
+ 'journeys_str',
+ [ 'arr_lat', 'arr_lon', ],
+ {
+ user_id => $uid,
+ cancelled => 0
+ },
+ {
+ limit => 1,
+ order_by => { -desc => 'journey_id' }
+ }
+ )->hash;
+
+ if ( not $res_h ) {
+ return;
+ }
+
+ return $res_h->{arr_lat}, $res_h->{arr_lon};
+
+}
+
+sub get_latest_checkout_ids {
my ( $self, %opt ) = @_;
my $uid = $opt{uid};
my $db = $opt{db} // $self->{pg}->db;
my $res_h = $db->select(
'journeys',
- ['checkout_station_id'],
+ [ 'checkout_station_id', 'backend_id', ],
{
user_id => $uid,
cancelled => 0
@@ -789,7 +855,7 @@ sub get_latest_checkout_station_id {
return;
}
- return $res_h->{checkout_station_id};
+ return $res_h->{checkout_station_id}, $res_h->{backend_id};
}
sub get_latest_checkout_stations {
@@ -800,7 +866,10 @@ sub get_latest_checkout_stations {
my $res = $db->select(
'journeys_str',
- [ 'arr_name', 'arr_eva', 'train_id' ],
+ [
+ 'arr_name', 'arr_eva', 'train_id', 'backend_id',
+ 'backend_name', 'is_hafas'
+ ],
{
user_id => $uid,
cancelled => 0
@@ -821,9 +890,10 @@ sub get_latest_checkout_stations {
push(
@ret,
{
- name => $row->{arr_name},
- eva => $row->{arr_eva},
- hafas => ( $row->{train_id} =~ m{[|]} ? 1 : 0 ),
+ name => $row->{arr_name},
+ eva => $row->{arr_eva},
+ hafas => $row->{is_hafas} ? $row->{backend_name} : 0,
+ backend_id => $row->{backend_id},
}
);
}
@@ -1082,19 +1152,62 @@ sub get_travel_distance {
->warn("Journey $journey->{id} has no from_name for EVA $from_eva");
}
+ # Work around inconsistencies caused by a multiple EVA IDs mapping to the same station name
+ if (
+ @{ $polyline_ref // [] }
+ and not List::MoreUtils::any { $_->[2] and $_->[2] == $from_eva }
+ @{ $polyline_ref // [] }
+ )
+ {
+ $self->{log}->debug(
+"Journey $journey->{id} from_eva ($from_eva) is not part of polyline"
+ );
+ for my $entry ( @{$route_ref} ) {
+ if ( $entry->[0] eq $from and $entry->[1] ) {
+ $from_eva = $entry->[1];
+ $self->{log}->debug("... setting to $from_eva");
+ last;
+ }
+ }
+ }
+ if (
+ @{ $polyline_ref // [] }
+ and not List::MoreUtils::any { $_->[2] and $_->[2] == $to_eva }
+ @{ $polyline_ref // [] }
+ )
+ {
+ $self->{log}->debug(
+ "Journey $journey->{id} to_eva ($to_eva) is not part of polyline");
+ for my $entry ( @{$route_ref} ) {
+ if ( $entry->[0] eq $to and $entry->[1] ) {
+ $to_eva = $entry->[1];
+ $self->{log}->debug("... setting to $to_eva");
+ last;
+ }
+ }
+ }
+
my $distance_polyline = 0;
my $distance_intermediate = 0;
- my $distance_beeline = 0;
- my $skipped = 0;
my $geo = GIS::Distance->new();
- my @stations = map { $_->[0] } @{$route_ref};
- my @route = after_incl { $_ eq $from } @stations;
- @route = before_incl { $_ eq $to } @route;
+ my $distance_beeline
+ = $geo->distance_metal( @{$from_latlon}, @{$to_latlon} );
+ my @route
+ = after_incl { ( $_->[1] and $_->[1] == $from_eva ) or $_->[0] eq $from }
+ @{$route_ref};
+ @route
+ = before_incl { ( $_->[1] and $_->[1] == $to_eva ) or $_->[0] eq $to }
+ @route;
- if ( @route < 2 ) {
+ if (
+ @route < 2
+ or ( $route[-1][0] ne $to
+ and ( not $route[-1][1] or $route[-1][1] != $to_eva ) )
+ )
+ {
# I AM ERROR
- return ( 0, 0, 0 );
+ return ( 0, 0, $distance_beeline );
}
my @polyline = after_incl { $_->[2] and $_->[2] == $from_eva }
@@ -1102,34 +1215,32 @@ sub get_travel_distance {
@polyline
= before_incl { $_->[2] and $_->[2] == $to_eva } @polyline;
- my $prev_station = shift @polyline;
- for my $station (@polyline) {
- $distance_polyline += $geo->distance_metal(
- $prev_station->[1], $prev_station->[0],
- $station->[1], $station->[0]
- );
- $prev_station = $station;
- }
-
- $prev_station = $self->{latlon_by_station}->{ shift @route };
- if ( not $prev_station ) {
- return ( $distance_polyline, 0, 0 );
- }
-
- for my $station_name (@route) {
- if ( my $station = $self->{latlon_by_station}->{$station_name} ) {
- $distance_intermediate += $geo->distance_metal(
- $prev_station->[0], $prev_station->[1],
- $station->[0], $station->[1]
+ # ensure that before_incl matched -- otherwise, @polyline is too long
+ if ( @polyline and $polyline[-1][2] == $to_eva ) {
+ my $prev_station = shift @polyline;
+ for my $station (@polyline) {
+ $distance_polyline += $geo->distance_metal(
+ $prev_station->[1], $prev_station->[0],
+ $station->[1], $station->[0]
);
$prev_station = $station;
}
}
- $distance_beeline = $geo->distance_metal( @{$from_latlon}, @{$to_latlon} );
+ if ( defined $route[0][2]{lat} and defined $route[0][2]{lon} ) {
+ my $prev_station = shift @route;
+ for my $station (@route) {
+ if ( defined $station->[2]{lat} and defined $station->[2]{lon} ) {
+ $distance_intermediate += $geo->distance_metal(
+ $prev_station->[2]{lat}, $prev_station->[2]{lon},
+ $station->[2]{lat}, $station->[2]{lon}
+ );
+ $prev_station = $station;
+ }
+ }
+ }
- return ( $distance_polyline, $distance_intermediate,
- $distance_beeline, $skipped );
+ return ( $distance_polyline, $distance_intermediate, $distance_beeline );
}
sub grep_single {
@@ -1694,28 +1805,29 @@ sub get_stats {
return $stats;
}
-sub get_latest_dest_id {
+sub get_latest_dest_ids {
my ( $self, %opt ) = @_;
my $uid = $opt{uid};
my $db = $opt{db} // $self->{pg}->db;
if (
- my $id = $self->{in_transit}->get_checkout_station_id(
+ my ( $id, $backend_id ) = $self->{in_transit}->get_checkout_ids(
uid => $uid,
db => $db
)
)
{
- return $id;
+ return ( $id, $backend_id );
}
- return $self->get_latest_checkout_station_id(
+ return $self->get_latest_checkout_ids(
uid => $uid,
db => $db
);
}
+# Returns a listref of {eva, name} hashrefs for the specified backend.
sub get_connection_targets {
my ( $self, %opt ) = @_;
@@ -1724,21 +1836,32 @@ sub get_connection_targets {
// DateTime->now( time_zone => 'Europe/Berlin' )->subtract( months => 4 );
my $db = $opt{db} //= $self->{pg}->db;
my $min_count = $opt{min_count} // 3;
+ my $dest_id = $opt{eva};
if ( $opt{destination_name} ) {
- return (
- [],
- [ { eva => $opt{eva}, name => $opt{destination_name} } ]
- );
+ return {
+ eva => $opt{eva},
+ name => $opt{destination_name}
+ };
}
- my $dest_id = $opt{eva} // $self->get_latest_dest_id(%opt);
+ my $backend_id = $opt{backend_id};
+
+ if ( not $dest_id ) {
+ ( $dest_id, $backend_id ) = $self->get_latest_dest_ids(%opt);
+ }
if ( not $dest_id ) {
- return ( [], [] );
+ return;
}
- my $dest_ids = [ $dest_id, $self->{stations}->get_meta( eva => $dest_id ) ];
+ my $dest_ids = [
+ $dest_id,
+ $self->{stations}->get_meta(
+ eva => $dest_id,
+ backend_id => $backend_id,
+ )
+ ];
my $res = $db->select(
'journeys',
@@ -1746,7 +1869,8 @@ sub get_connection_targets {
{
user_id => $uid,
checkin_station_id => $dest_ids,
- real_departure => { '>', $threshold }
+ real_departure => { '>', $threshold },
+ backend_id => $opt{backend_id},
},
{
group_by => ['checkout_station_id'],
@@ -1756,8 +1880,11 @@ sub get_connection_targets {
my @destinations
= $res->hashes->grep( sub { shift->{count} >= $min_count } )
->map( sub { shift->{dest} } )->each;
- @destinations = $self->{stations}->get_by_evas(@destinations);
- return ( $dest_ids, \@destinations );
+ @destinations = $self->{stations}->get_by_evas(
+ backend_id => $opt{backend_id},
+ evas => [@destinations]
+ );
+ return @destinations;
}
sub update_visibility {
diff --git a/lib/Travelynx/Model/Stations.pm b/lib/Travelynx/Model/Stations.pm
index ac4019c..76fd452 100644
--- a/lib/Travelynx/Model/Stations.pm
+++ b/lib/Travelynx/Model/Stations.pm
@@ -14,38 +14,125 @@ sub new {
return bless( \%opt, $class );
}
-sub add_or_update {
+sub get_backend_id {
my ( $self, %opt ) = @_;
- my $stop = $opt{stop};
- my $loc = $stop->loc;
- my $source = 1;
- my $db = $opt{db} // $self->{pg}->db;
-
- if ( my $s = $self->get_by_eva( $loc->eva, db => $db ) ) {
- if ( $source == 1 and $s->{source} == 0 and not $s->{archived} ) {
- return;
+
+ if ( $opt{iris} ) {
+
+ # special case
+ return 0;
+ }
+ if ( $opt{hafas} and $self->{backend_id}{hafas}{ $opt{hafas} } ) {
+ return $self->{backend_id}{hafas}{ $opt{hafas} };
+ }
+
+ my $db = $opt{db} // $self->{pg}->db;
+ my $backend_id = 0;
+
+ if ( $opt{hafas} ) {
+ $backend_id = $db->select(
+ 'backends',
+ ['id'],
+ {
+ hafas => 1,
+ name => $opt{hafas}
+ }
+ )->hash->{id};
+ $self->{backend_id}{hafas}{ $opt{hafas} } = $backend_id;
+ }
+
+ return $backend_id;
+}
+
+sub get_hafas_name {
+ my ( $self, %opt ) = @_;
+
+ if ( exists $self->{hafas_name}{ $opt{backend_id} } ) {
+ return $self->{hafas_name}{ $opt{backend_id} };
+ }
+
+ my $db = $opt{db} // $self->{pg}->db;
+ my $hafas_name;
+ my $ret = $db->select(
+ 'backends',
+ ['name'],
+ {
+ hafas => 1,
+ id => $opt{backend_id},
}
- $db->update(
+ )->hash;
+
+ if ($ret) {
+ $hafas_name = $ret->{name};
+ }
+
+ $self->{hafas_name}{ $opt{backend_id} } = $hafas_name;
+
+ return $hafas_name;
+}
+
+sub get_backends {
+ my ( $self, %opt ) = @_;
+
+ $opt{db} //= $self->{pg}->db;
+
+ my $res = $opt{db}->select( 'backends', [ 'id', 'name', 'iris', 'hafas' ] );
+ my @ret;
+
+ while ( my $row = $res->hash ) {
+ push(
+ @ret,
+ {
+ id => $row->{id},
+ name => $row->{name},
+ iris => $row->{iris},
+ hafas => $row->{hafas},
+ }
+ );
+ }
+
+ return @ret;
+}
+
+sub add_or_update {
+ my ( $self, %opt ) = @_;
+ my $stop = $opt{stop};
+ my $loc = $stop->loc;
+ $opt{db} //= $self->{pg}->db;
+
+ $opt{backend_id} //= $self->get_backend_id(%opt);
+
+ if (
+ my $s = $self->get_by_eva(
+ $loc->eva,
+ db => $opt{db},
+ backend_id => $opt{backend_id}
+ )
+ )
+ {
+ $opt{db}->update(
'stations',
{
name => $loc->name,
lat => $loc->lat,
lon => $loc->lon,
- source => $source,
archived => 0
},
- { eva => $loc->eva }
+ {
+ eva => $loc->eva,
+ source => $opt{backend_id}
+ }
);
return;
}
- $db->insert(
+ $opt{db}->insert(
'stations',
{
eva => $loc->eva,
name => $loc->name,
lat => $loc->lat,
lon => $loc->lon,
- source => $source,
+ source => $opt{backend_id},
archived => 0
}
);
@@ -53,17 +140,20 @@ sub add_or_update {
sub add_meta {
my ( $self, %opt ) = @_;
- my $db = $opt{db} // $self->{pg}->db;
my $eva = $opt{eva};
my @meta = @{ $opt{meta} };
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
+
for my $meta (@meta) {
if ( $meta != $eva ) {
- $db->insert(
+ $opt{db}->insert(
'related_stations',
{
- eva => $eva,
- meta => $meta
+ eva => $eva,
+ meta => $meta,
+ backend_id => $opt{backend_id},
},
{ on_conflict => undef }
);
@@ -74,7 +164,7 @@ sub add_meta {
sub get_db_iterator {
my ($self) = @_;
- return $self->{pg}->db->select( 'stations', '*' );
+ return $self->{pg}->db->select( 'stations_str', '*' );
}
sub get_meta {
@@ -82,7 +172,16 @@ sub get_meta {
my $db = $opt{db} // $self->{pg}->db;
my $eva = $opt{eva};
- my $res = $db->select( 'related_stations', ['meta'], { eva => $eva } );
+ $opt{backend_id} //= $self->get_backend_id( %opt, db => $db );
+
+ my $res = $db->select(
+ 'related_stations',
+ ['meta'],
+ {
+ eva => $eva,
+ backend_id => $opt{backend_id}
+ }
+ );
my @ret;
while ( my $row = $res->hash ) {
@@ -93,9 +192,12 @@ sub get_meta {
}
sub get_for_autocomplete {
- my ($self) = @_;
+ my ( $self, %opt ) = @_;
+
+ $opt{backend_id} //= $self->get_backend_id(%opt);
- my $res = $self->{pg}->db->select( 'stations', ['name'] );
+ my $res = $self->{pg}
+ ->db->select( 'stations', ['name'], { source => $opt{backend_id} } );
my %ret;
while ( my $row = $res->hash ) {
@@ -113,43 +215,53 @@ sub get_by_eva {
return;
}
- my $db = $opt{db} // $self->{pg}->db;
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
- return $db->select( 'stations', '*', { eva => $eva } )->hash;
+ return $opt{db}->select(
+ 'stations',
+ '*',
+ {
+ eva => $eva,
+ source => $opt{backend_id}
+ }
+ )->hash;
}
# Fast
sub get_by_evas {
- my ( $self, @evas ) = @_;
-
- my @ret
- = $self->{pg}->db->select( 'stations', '*', { eva => { '=', \@evas } } )
- ->hashes->each;
- return @ret;
-}
-
-# Slow
-sub get_latlon_by_name {
my ( $self, %opt ) = @_;
- my $db = $opt{db} // $self->{pg}->db;
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
- my %location;
- my $res = $db->select( 'stations', [ 'name', 'lat', 'lon' ] );
- while ( my $row = $res->hash ) {
- $location{ $row->{name} } = [ $row->{lat}, $row->{lon} ];
- }
- return \%location;
+ my @ret = $self->{pg}->db->select(
+ 'stations',
+ '*',
+ {
+ eva => { '=', $opt{evas} },
+ source => $opt{backend_id}
+ }
+ )->hashes->each;
+ return @ret;
}
# Slow
sub get_by_name {
my ( $self, $name, %opt ) = @_;
- my $db = $opt{db} // $self->{pg}->db;
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
- return $db->select( 'stations', '*', { name => $name }, { limit => 1 } )
- ->hash;
+ return $opt{db}->select(
+ 'stations',
+ '*',
+ {
+ name => $name,
+ source => $opt{backend_id}
+ },
+ { limit => 1 }
+ )->hash;
}
# Slow
@@ -166,16 +278,27 @@ sub get_by_names {
sub get_by_ds100 {
my ( $self, $ds100, %opt ) = @_;
- my $db = $opt{db} // $self->{pg}->db;
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
- return $db->select( 'stations', '*', { ds100 => $ds100 }, { limit => 1 } )
- ->hash;
+ return $opt{db}->select(
+ 'stations',
+ '*',
+ {
+ ds100 => $ds100,
+ source => $opt{backend_id}
+ },
+ { limit => 1 }
+ )->hash;
}
# Can be slow
sub search {
my ( $self, $identifier, %opt ) = @_;
+ $opt{db} //= $self->{pg}->db;
+ $opt{backend_id} //= $self->get_backend_id(%opt);
+
if ( $identifier =~ m{ ^ \d+ $ }x ) {
return $self->get_by_eva( $identifier, %opt )
// $self->get_by_ds100( $identifier, %opt )
diff --git a/lib/Travelynx/Model/Traewelling.pm b/lib/Travelynx/Model/Traewelling.pm
index 25648cc..c460b1a 100644
--- a/lib/Travelynx/Model/Traewelling.pm
+++ b/lib/Travelynx/Model/Traewelling.pm
@@ -224,6 +224,7 @@ sub get_pushable_accounts {
join in_transit_str as i on t.user_id = i.user_id
where t.push_sync = True
and i.arr_eva is not null
+ and i.backend_id <= 1
and i.cancelled = False
}
);
diff --git a/lib/Travelynx/Model/Users.pm b/lib/Travelynx/Model/Users.pm
index 4602fa2..7d3777b 100644
--- a/lib/Travelynx/Model/Users.pm
+++ b/lib/Travelynx/Model/Users.pm
@@ -40,14 +40,6 @@ my %predicate_atoi = (
is_blocked_by => 3,
);
-my @sb_templates = (
- undef,
- [ 'DBF', 'https://dbf.finalrewind.org/{name}?rt=1#{tt}{tn}' ],
- [ 'bahn.expert', 'https://bahn.expert/{name}#{id}' ],
- [ 'DBF HAFAS', 'https://dbf.finalrewind.org/{name}?rt=1&hafas=1#{tt}{tn}' ],
- [ 'bahn.expert/regional', 'https://bahn.expert/regional/{name}#{id}' ],
-);
-
my %token_id = (
status => 1,
history => 2,
@@ -213,6 +205,13 @@ sub get_privacy_by {
return;
}
+sub set_backend {
+ my ( $self, %opt ) = @_;
+ $opt{db} //= $self->{pg}->db;
+
+ $opt{db}->update('users', {backend_id => $opt{backend_id}}, {id => $opt{uid}});
+}
+
sub set_privacy {
my ( $self, %opt ) = @_;
my $db = $opt{db} // $self->{pg}->db;
@@ -409,12 +408,13 @@ sub get {
my $uid = $opt{uid};
my $user = $db->select(
- 'users',
+ 'users_with_backend',
'id, name, status, public_level, email, '
- . 'external_services, accept_follows, notifications, '
+ . 'accept_follows, notifications, '
. 'extract(epoch from registered_at) as registered_at_ts, '
. 'extract(epoch from last_seen) as last_seen_ts, '
- . 'extract(epoch from deletion_requested) as deletion_requested_ts',
+ . 'extract(epoch from deletion_requested) as deletion_requested_ts, '
+ . 'backend_id, backend_name, hafas',
{ id => $uid }
)->hash;
if ($user) {
@@ -435,12 +435,8 @@ sub get {
past_status => $user->{public_level} & 0x08000 ? 1 : 0,
past_all => $user->{public_level} & 0x10000 ? 1 : 0,
email => $user->{email},
- sb_name => $user->{external_services}
- ? $sb_templates[ $user->{external_services} & 0x07 ][0]
- : undef,
- sb_template => $user->{external_services}
- ? $sb_templates[ $user->{external_services} & 0x07 ][1]
- : undef,
+ sb_template =>
+ 'https://dbf.finalrewind.org/{name}?rt=1&hafas={hafas}#{tt}{tn}',
registered_at => DateTime->from_epoch(
epoch => $user->{registered_at_ts},
time_zone => 'Europe/Berlin'
@@ -455,6 +451,9 @@ sub get {
time_zone => 'Europe/Berlin'
)
: undef,
+ backend_id => $user->{backend_id},
+ backend_name => $user->{backend_name},
+ backend_hafas => $user->{hafas},
};
}
return undef;
@@ -659,24 +658,6 @@ sub use_history {
}
}
-sub use_external_services {
- my ( $self, %opt ) = @_;
- my $db = $opt{db} // $self->{pg}->db;
- my $uid = $opt{uid};
- my $value = $opt{set};
-
- if ( defined $value ) {
- if ( $value < 0 or $value > 4 ) {
- $value = 0;
- }
- $db->update( 'users', { external_services => $value }, { id => $uid } );
- }
- else {
- return $db->select( 'users', ['external_services'], { id => $uid } )
- ->hash->{external_services};
- }
-}
-
sub get_webhook {
my ( $self, %opt ) = @_;
my $db = $opt{db} // $self->{pg}->db;