summaryrefslogtreecommitdiff
path: root/lib/Travelynx/Model/Journeys.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Travelynx/Model/Journeys.pm')
-rwxr-xr-xlib/Travelynx/Model/Journeys.pm130
1 files changed, 96 insertions, 34 deletions
diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm
index 343d680..b07511a 100755
--- a/lib/Travelynx/Model/Journeys.pm
+++ b/lib/Travelynx/Model/Journeys.pm
@@ -4,16 +4,16 @@ package Travelynx::Model::Journeys;
#
# SPDX-License-Identifier: AGPL-3.0-or-later
-use GIS::Distance;
-use List::MoreUtils qw(after_incl before_incl);
-
use strict;
use warnings;
use 5.020;
use utf8;
use DateTime;
+use DateTime::Format::Strptime;
+use GIS::Distance;
use JSON;
+use List::MoreUtils qw(after_incl before_incl);
my %visibility_itoa = (
100 => 'public',
@@ -183,20 +183,44 @@ sub add {
}
if ( $opt{route} ) {
+ my $parser = DateTime::Format::Strptime->new(
+ pattern => '%d.%m.%Y %H:%M',
+ locale => 'de_DE',
+ time_zone => 'Europe/Berlin'
+ );
my @unknown_stations;
+ my $prev_epoch = 0;
+
for my $station ( @{ $opt{route} } ) {
+ my $ts;
+ my %station_data;
+ if ( $station
+ =~ m{ ^ (?<stop> [^@]+? ) \s* [@] \s* (?<timestamp> .+ ) $ }x )
+ {
+ $station = $+{stop};
+ $ts = $parser->parse_datetime( $+{timestamp} );
+ if ($ts) {
+ my $epoch = $ts->epoch;
+ if ( $epoch < $prev_epoch ) {
+ return ( undef,
+'Zeitstempel der Unterwegshalte müssen monoton steigend sein (keine Zeitreisen und keine Portale)'
+ );
+ }
+ $station_data{sched_arr} = $epoch;
+ $station_data{sched_dep} = $epoch;
+ $prev_epoch = $epoch;
+ }
+ }
my $station_info = $self->{stations}
->search( $station, backend_id => $opt{backend_id} );
if ($station_info) {
+ $station_data{lat} = $station_info->{lat};
+ $station_data{lon} = $station_info->{lon};
push(
@route,
[
- $station_info->{name},
- $station_info->{eva},
- {
- lat => $station_info->{lat},
- lon => $station_info->{lon},
- }
+ $station_info->{name}, $station_info->{eva},
+ \%station_data,
]
);
}
@@ -283,8 +307,14 @@ sub add_from_in_transit {
my $db = $opt{db};
my $journey = $opt{journey};
+ if ( $journey->{train_id} eq 'manual' ) {
+ $journey->{edited} = 0x3fff;
+ }
+ else {
+ $journey->{edited} = 0;
+ }
+
delete $journey->{data};
- $journey->{edited} = 0;
$journey->{checkout_time} = DateTime->now( time_zone => 'Europe/Berlin' );
return $db->insert( 'journeys', $journey, { returning => 'id' } )
@@ -301,10 +331,11 @@ sub update {
my $rows;
my $journey = $self->get_single(
- uid => $uid,
- db => $db,
- journey_id => $journey_id,
- with_datetime => 1,
+ uid => $uid,
+ db => $db,
+ journey_id => $journey_id,
+ with_datetime => 1,
+ with_route_datetime => 1,
);
eval {
@@ -548,7 +579,7 @@ sub get {
my @select
= (
- 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)
+ qw(journey_id is_dbris is_iris is_hafas is_motis 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_platform dep_lat dep_lon checkout_ts sched_arr_ts real_arr_ts arr_eva arr_ds100 arr_name arr_platform arr_lat arr_lon cancelled edited route messages user_data visibility effective_visibility)
);
my %where = (
user_id => $uid,
@@ -606,16 +637,19 @@ sub get {
my $ref = {
id => $entry->{journey_id},
+ is_dbris => $entry->{is_dbris},
is_iris => $entry->{is_iris},
is_hafas => $entry->{is_hafas},
+ is_motis => $entry->{is_motis},
backend_name => $entry->{backend_name},
backend_id => $entry->{backend_id},
- type => $entry->{train_type},
+ type => $entry->{train_type} =~ s{ \s+ $ }{}rx,
line => $entry->{train_line},
no => $entry->{train_no},
from_eva => $entry->{dep_eva},
from_ds100 => $entry->{dep_ds100},
from_name => $entry->{dep_name},
+ from_platform => $entry->{dep_platform},
from_latlon => [ $entry->{dep_lat}, $entry->{dep_lon} ],
checkin_ts => $entry->{checkin_ts},
sched_dep_ts => $entry->{sched_dep_ts},
@@ -623,6 +657,7 @@ sub get {
to_eva => $entry->{arr_eva},
to_ds100 => $entry->{arr_ds100},
to_name => $entry->{arr_name},
+ to_platform => $entry->{arr_platform},
to_latlon => [ $entry->{arr_lat}, $entry->{arr_lon} ],
checkout_ts => $entry->{checkout_ts},
sched_arr_ts => $entry->{sched_arr_ts},
@@ -656,6 +691,14 @@ sub get {
$ref->{checkout} = epoch_to_dt( $ref->{checkout_ts} );
$ref->{sched_arrival} = epoch_to_dt( $ref->{sched_arr_ts} );
$ref->{rt_arrival} = epoch_to_dt( $ref->{rt_arr_ts} );
+ if ( $ref->{rt_dep_ts} and $ref->{sched_dep_ts} ) {
+ $ref->{delay_dep} = $ref->{rt_dep_ts} - $ref->{sched_dep_ts};
+ }
+ if ( $ref->{rt_arr_ts} and $ref->{sched_arr_ts} ) {
+ $ref->{delay_arr} = $ref->{rt_arr_ts} - $ref->{sched_arr_ts};
+ }
+ }
+ if ( $opt{with_route_datetime} ) {
for my $stop ( @{ $ref->{route} } ) {
for my $k (qw(rt_arr rt_dep sched_arr sched_dep)) {
if ( $stop->[2]{$k} ) {
@@ -867,8 +910,11 @@ sub get_latest_checkout_stations {
my $res = $db->select(
'journeys_str',
[
- 'arr_name', 'arr_eva', 'train_id', 'backend_id',
- 'backend_name', 'is_hafas'
+ 'arr_name', 'arr_eva',
+ 'arr_external_id', 'train_id',
+ 'backend_id', 'backend_name',
+ 'is_dbris', 'is_efa',
+ 'is_hafas', 'is_motis'
],
{
user_id => $uid,
@@ -890,9 +936,14 @@ sub get_latest_checkout_stations {
push(
@ret,
{
- name => $row->{arr_name},
- eva => $row->{arr_eva},
+ name => $row->{arr_name},
+ eva => $row->{arr_eva},
+ external_id_or_eva => $row->{arr_external_id}
+ // $row->{arr_eva},
+ dbris => $row->{is_dbris} ? $row->{backend_name} : 0,
+ efa => $row->{is_efa} ? $row->{backend_name} : 0,
hafas => $row->{is_hafas} ? $row->{backend_name} : 0,
+ motis => $row->{is_motis} ? $row->{backend_name} : 0,
backend_id => $row->{backend_id},
}
);
@@ -1091,32 +1142,33 @@ sub sanity_check {
if ( defined $journey->{sched_duration}
and $journey->{sched_duration} <= 0 )
{
- return
-'Die geplante Dauer dieser Fahrt ist ≤ 0. Teleportation und Zeitreisen werden aktuell nicht unterstützt.';
+ return 'Die geplante Dauer dieser Fahrt ist ≤ 0.'
+ . ' Teleportation und Zeitreisen werden in diesem Universum nicht unterstützt.';
}
if ( defined $journey->{rt_duration}
and $journey->{rt_duration} <= 0 )
{
- return
-'Die Dauer dieser Fahrt ist ≤ 0. Teleportation und Zeitreisen werden aktuell nicht unterstützt.';
+ return 'Die Dauer dieser Fahrt ist ≤ 0.'
+ . ' Teleportation und Zeitreisen werden in diesem Universum nicht unterstützt.';
}
if ( $journey->{sched_duration}
- and $journey->{sched_duration} > 60 * 60 * 24 )
+ and $journey->{sched_duration} > 60 * 60 * 72 )
{
- return 'Die Fahrt ist länger als 24 Stunden.';
+ return 'Die Fahrt ist länger als drei Tage.';
}
if ( $journey->{rt_duration}
- and $journey->{rt_duration} > 60 * 60 * 24 )
+ and $journey->{rt_duration} > 60 * 60 * 72 )
{
- return 'Die Fahrt ist länger als 24 Stunden.';
+ return 'Die Fahrt ist länger als drei Tage.';
}
if ( $journey->{kmh_route} > 500 or $journey->{kmh_beeline} > 500 ) {
- return 'Fahrten mit über 500 km/h? Schön wär\'s.';
+ return 'Die berechnete Geschwindigkeit beträgt über 500 km/h.'
+ . ' Das wirkt unrealistisch.';
}
if ( $journey->{route} and @{ $journey->{route} } > 199 ) {
my $stop_count = @{ $journey->{route} };
- return
-"Die Fahrt hat $stop_count Unterwegshalte. Also ich weiß ja nicht so recht.";
+ return "Die Fahrt hat $stop_count Unterwegshalte. "
+ . ' Stimmt das wirklich?';
}
if ( $journey->{edited} & 0x0010 and not $lax ) {
my @unknown_stations
@@ -1659,7 +1711,10 @@ sub compute_stats {
@inconsistencies,
{
conflict => {
- train => $journey->{type} . ' '
+ train => (
+ $journey->{is_motis} ? '' : $journey->{type}
+ )
+ . ' '
. ( $journey->{line} // $journey->{no} ),
arr => epoch_to_dt( $journey->{rt_arr_ts} )
->strftime('%d.%m.%Y %H:%M'),
@@ -1685,7 +1740,8 @@ sub compute_stats {
$next_departure = $journey->{rt_dep_ts};
$next_id = $journey->{id};
$next_train
- = $journey->{type} . ' ' . ( $journey->{line} // $journey->{no} ),;
+ = ( $journey->{is_motis} ? '' : $journey->{type} ) . ' '
+ . ( $journey->{line} // $journey->{no} ),;
}
my $ret = {
km_route => $km_route,
@@ -1718,6 +1774,8 @@ sub compute_stats {
sub get_stats {
my ( $self, %opt ) = @_;
+ $self->{log}->debug("get_stats");
+
if ( $opt{cancelled} ) {
$self->{log}
->warn('get_journey_stats called with illegal option cancelled => 1');
@@ -1744,9 +1802,12 @@ sub get_stats {
)
)
{
+ $self->{log}->debug("got cached journey stats for $year/$month");
return $stats;
}
+ $self->{log}->debug("computing journey stats for $year/$month");
+
my $interval_start = DateTime->new(
time_zone => 'Europe/Berlin',
year => 2000,
@@ -1879,7 +1940,8 @@ sub get_connection_targets {
);
my @destinations
= $res->hashes->grep( sub { shift->{count} >= $min_count } )
- ->map( sub { shift->{dest} } )->each;
+ ->map( sub { shift->{dest} } )
+ ->each;
@destinations = $self->{stations}->get_by_evas(
backend_id => $opt{backend_id},
evas => [@destinations]