From 3f4fc57ba097ce969031ab1a1398d4bb657ca056 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Fri, 28 Oct 2022 22:51:15 +0200 Subject: Use T-S-DE-HAFAS rather than transport.rest for map Squashed commit of the following: commit ebba74fa1f732c12a4323a7b58df56e02bcb7953 Author: Daniel Friesel Date: Fri Oct 28 22:50:52 2022 +0200 update cpanfile.snapshot commit a6248cca63a96cb6a94723d017e58c7064b5fa73 Author: Daniel Friesel Date: Fri Oct 28 22:30:38 2022 +0200 cpanfile: requires T-S-DE-HAFAS commit c4b8357736976f54b2c32343210dd3612a7d60fe Author: Daniel Friesel Date: Fri Oct 28 22:28:41 2022 +0200 map: handle cancelled arrivals / stops commit 70bbd2bd1270ca10cb2f72aad333d265d0936a18 Author: Daniel Friesel Date: Thu Oct 27 23:01:24 2022 +0200 transport.rest is no longer in use commit d43e985785759b3eecfd0f6912e6e0266de24ba4 Author: Daniel Friesel Date: Thu Oct 27 22:59:28 2022 +0200 about: map is now served via T-S-DE-HAFAS commit 382262e29f00b8b0425366fa847d4d07c59ce0a1 Author: Daniel Friesel Date: Wed Oct 26 22:44:36 2022 +0200 map: update T-S-DE-HAFAS API commit 7e5f1e5c7d1ffaa5bdbbbf61124983e6c6e7fdd8 Author: Daniel Friesel Date: Tue Oct 25 21:19:16 2022 +0200 Use Travel::Status::DE::HAFAS 4.00 (unreleased) instead of transport.rest commit 706179018143d0cad4c1d5c05f110ff084dd5bc7 Author: Daniel Friesel Date: Sun Oct 16 22:44:22 2022 +0200 remove unused and unmaintained train intersection code --- cpanfile | 1 + cpanfile.snapshot | 1099 ++++++++++++++++++------------------ lib/DBInfoscreen.pm | 3 - lib/DBInfoscreen/Controller/Map.pm | 543 +++--------------- lib/DBInfoscreen/Helper/HAFAS.pm | 66 +-- templates/about.html.ep | 9 +- 6 files changed, 660 insertions(+), 1061 deletions(-) diff --git a/cpanfile b/cpanfile index dc37df1..df8800e 100644 --- a/cpanfile +++ b/cpanfile @@ -10,5 +10,6 @@ requires 'LWP::UserAgent'; requires 'LWP::Protocol::https'; requires 'Mojolicious'; requires 'Travel::Status::DE::DBWagenreihung', '0.06'; +requires 'Travel::Status::DE::HAFAS', '4.00'; requires 'Travel::Status::DE::IRIS'; requires 'XML::LibXML'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 5dfb49c..1e9c769 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -1,86 +1,87 @@ # carton snapshot format: version 1.0 DISTRIBUTIONS - Alien-Build-2.70 - pathname: P/PL/PLICEASE/Alien-Build-2.70.tar.gz - provides: - Alien::Base 2.70 - Alien::Base::PkgConfig 2.70 - Alien::Base::Wrapper 2.70 - Alien::Build 2.70 - Alien::Build::CommandSequence 2.70 - Alien::Build::Helper 2.70 - Alien::Build::Interpolate 2.70 - Alien::Build::Interpolate::Default 2.70 - Alien::Build::Interpolate::Helper 2.70 - Alien::Build::Log 2.70 - Alien::Build::Log::Abbreviate 2.70 - Alien::Build::Log::Default 2.70 - Alien::Build::MM 2.70 - Alien::Build::Meta 2.70 - Alien::Build::Plugin 2.70 - Alien::Build::Plugin::Build::Autoconf 2.70 - Alien::Build::Plugin::Build::CMake 2.70 - Alien::Build::Plugin::Build::Copy 2.70 - Alien::Build::Plugin::Build::MSYS 2.70 - Alien::Build::Plugin::Build::Make 2.70 - Alien::Build::Plugin::Build::SearchDep 2.70 - Alien::Build::Plugin::Core::CleanInstall 2.70 - Alien::Build::Plugin::Core::Download 2.70 - Alien::Build::Plugin::Core::FFI 2.70 - Alien::Build::Plugin::Core::Gather 2.70 - Alien::Build::Plugin::Core::Legacy 2.70 - Alien::Build::Plugin::Core::Override 2.70 - Alien::Build::Plugin::Core::Setup 2.70 - Alien::Build::Plugin::Core::Tail 2.70 - Alien::Build::Plugin::Decode::DirListing 2.70 - Alien::Build::Plugin::Decode::DirListingFtpcopy 2.70 - Alien::Build::Plugin::Decode::HTML 2.70 - Alien::Build::Plugin::Decode::Mojo 2.70 - Alien::Build::Plugin::Digest::Negotiate 2.70 - Alien::Build::Plugin::Digest::SHA 2.70 - Alien::Build::Plugin::Digest::SHAPP 2.70 - Alien::Build::Plugin::Download::Negotiate 2.70 - Alien::Build::Plugin::Extract::ArchiveTar 2.70 - Alien::Build::Plugin::Extract::ArchiveZip 2.70 - Alien::Build::Plugin::Extract::CommandLine 2.70 - Alien::Build::Plugin::Extract::Directory 2.70 - Alien::Build::Plugin::Extract::Negotiate 2.70 - Alien::Build::Plugin::Fetch::CurlCommand 2.70 - Alien::Build::Plugin::Fetch::HTTPTiny 2.70 - Alien::Build::Plugin::Fetch::LWP 2.70 - Alien::Build::Plugin::Fetch::Local 2.70 - Alien::Build::Plugin::Fetch::LocalDir 2.70 - Alien::Build::Plugin::Fetch::NetFTP 2.70 - Alien::Build::Plugin::Fetch::Wget 2.70 - Alien::Build::Plugin::Gather::IsolateDynamic 2.70 - Alien::Build::Plugin::PkgConfig::CommandLine 2.70 - Alien::Build::Plugin::PkgConfig::LibPkgConf 2.70 - Alien::Build::Plugin::PkgConfig::MakeStatic 2.70 - Alien::Build::Plugin::PkgConfig::Negotiate 2.70 - Alien::Build::Plugin::PkgConfig::PP 2.70 - Alien::Build::Plugin::Prefer::BadVersion 2.70 - Alien::Build::Plugin::Prefer::GoodVersion 2.70 - Alien::Build::Plugin::Prefer::SortVersions 2.70 - Alien::Build::Plugin::Probe::CBuilder 2.70 - Alien::Build::Plugin::Probe::CommandLine 2.70 - Alien::Build::Plugin::Probe::Vcpkg 2.70 - Alien::Build::Plugin::Test::Mock 2.70 - Alien::Build::PluginMeta 2.70 - Alien::Build::Temp 2.70 - Alien::Build::TempDir 2.70 - Alien::Build::Util 2.70 - Alien::Build::Version::Basic 2.70 - Alien::Build::rc 2.70 - Alien::Role 2.70 - Alien::Util 2.70 - Test::Alien 2.70 - Test::Alien::Build 2.70 - Test::Alien::CanCompile 2.70 - Test::Alien::CanPlatypus 2.70 - Test::Alien::Diag 2.70 - Test::Alien::Run 2.70 - Test::Alien::Synthetic 2.70 - alienfile 2.70 + Alien-Build-2.72 + pathname: P/PL/PLICEASE/Alien-Build-2.72.tar.gz + provides: + Alien::Base 2.72 + Alien::Base::PkgConfig 2.72 + Alien::Base::Wrapper 2.72 + Alien::Build 2.72 + Alien::Build::CommandSequence 2.72 + Alien::Build::Helper 2.72 + Alien::Build::Interpolate 2.72 + Alien::Build::Interpolate::Default 2.72 + Alien::Build::Interpolate::Helper 2.72 + Alien::Build::Log 2.72 + Alien::Build::Log::Abbreviate 2.72 + Alien::Build::Log::Default 2.72 + Alien::Build::MM 2.72 + Alien::Build::Meta 2.72 + Alien::Build::Plugin 2.72 + Alien::Build::Plugin::Build::Autoconf 2.72 + Alien::Build::Plugin::Build::CMake 2.72 + Alien::Build::Plugin::Build::Copy 2.72 + Alien::Build::Plugin::Build::MSYS 2.72 + Alien::Build::Plugin::Build::Make 2.72 + Alien::Build::Plugin::Build::SearchDep 2.72 + Alien::Build::Plugin::Core::CleanInstall 2.72 + Alien::Build::Plugin::Core::Download 2.72 + Alien::Build::Plugin::Core::FFI 2.72 + Alien::Build::Plugin::Core::Gather 2.72 + Alien::Build::Plugin::Core::Legacy 2.72 + Alien::Build::Plugin::Core::Override 2.72 + Alien::Build::Plugin::Core::Setup 2.72 + Alien::Build::Plugin::Core::Tail 2.72 + Alien::Build::Plugin::Decode::DirListing 2.72 + Alien::Build::Plugin::Decode::DirListingFtpcopy 2.72 + Alien::Build::Plugin::Decode::HTML 2.72 + Alien::Build::Plugin::Decode::Mojo 2.72 + Alien::Build::Plugin::Digest::Negotiate 2.72 + Alien::Build::Plugin::Digest::SHA 2.72 + Alien::Build::Plugin::Digest::SHAPP 2.72 + Alien::Build::Plugin::Download::Negotiate 2.72 + Alien::Build::Plugin::Extract::ArchiveTar 2.72 + Alien::Build::Plugin::Extract::ArchiveZip 2.72 + Alien::Build::Plugin::Extract::CommandLine 2.72 + Alien::Build::Plugin::Extract::Directory 2.72 + Alien::Build::Plugin::Extract::File 2.72 + Alien::Build::Plugin::Extract::Negotiate 2.72 + Alien::Build::Plugin::Fetch::CurlCommand 2.72 + Alien::Build::Plugin::Fetch::HTTPTiny 2.72 + Alien::Build::Plugin::Fetch::LWP 2.72 + Alien::Build::Plugin::Fetch::Local 2.72 + Alien::Build::Plugin::Fetch::LocalDir 2.72 + Alien::Build::Plugin::Fetch::NetFTP 2.72 + Alien::Build::Plugin::Fetch::Wget 2.72 + Alien::Build::Plugin::Gather::IsolateDynamic 2.72 + Alien::Build::Plugin::PkgConfig::CommandLine 2.72 + Alien::Build::Plugin::PkgConfig::LibPkgConf 2.72 + Alien::Build::Plugin::PkgConfig::MakeStatic 2.72 + Alien::Build::Plugin::PkgConfig::Negotiate 2.72 + Alien::Build::Plugin::PkgConfig::PP 2.72 + Alien::Build::Plugin::Prefer::BadVersion 2.72 + Alien::Build::Plugin::Prefer::GoodVersion 2.72 + Alien::Build::Plugin::Prefer::SortVersions 2.72 + Alien::Build::Plugin::Probe::CBuilder 2.72 + Alien::Build::Plugin::Probe::CommandLine 2.72 + Alien::Build::Plugin::Probe::Vcpkg 2.72 + Alien::Build::Plugin::Test::Mock 2.72 + Alien::Build::PluginMeta 2.72 + Alien::Build::Temp 2.72 + Alien::Build::TempDir 2.72 + Alien::Build::Util 2.72 + Alien::Build::Version::Basic 2.72 + Alien::Build::rc 2.72 + Alien::Role 2.72 + Alien::Util 2.72 + Test::Alien 2.72 + Test::Alien::Build 2.72 + Test::Alien::CanCompile 2.72 + Test::Alien::CanPlatypus 2.72 + Test::Alien::Diag 2.72 + Test::Alien::Run 2.72 + Test::Alien::Synthetic 2.72 + alienfile 2.72 requirements: Capture::Tiny 0.17 Digest::SHA 0 @@ -257,6 +258,12 @@ DISTRIBUTIONS perl 5.008001 strict 0 warnings 0 + Clone-0.46 + pathname: G/GA/GARU/Clone-0.46.tar.gz + provides: + Clone 0.46 + requirements: + ExtUtils::MakeMaker 0 Const-Fast-0.014 pathname: L/LE/LEONT/Const-Fast-0.014.tar.gz provides: @@ -281,19 +288,19 @@ DISTRIBUTIONS Sub::Install 0.921 strict 0 warnings 0 - DateTime-1.58 - pathname: D/DR/DROLSKY/DateTime-1.58.tar.gz - provides: - DateTime 1.58 - DateTime::Duration 1.58 - DateTime::Helpers 1.58 - DateTime::Infinite 1.58 - DateTime::Infinite::Future 1.58 - DateTime::Infinite::Past 1.58 - DateTime::LeapSecond 1.58 - DateTime::PP 1.58 - DateTime::PPExtra 1.58 - DateTime::Types 1.58 + DateTime-1.59 + pathname: D/DR/DROLSKY/DateTime-1.59.tar.gz + provides: + DateTime 1.59 + DateTime::Duration 1.59 + DateTime::Helpers 1.59 + DateTime::Infinite 1.59 + DateTime::Infinite::Future 1.59 + DateTime::Infinite::Past 1.59 + DateTime::LeapSecond 1.59 + DateTime::PP 1.59 + DateTime::PPExtra 1.59 + DateTime::Types 1.59 requirements: Carp 0 DateTime::Locale 1.06 @@ -312,7 +319,6 @@ DISTRIBUTIONS Specio::Subs 0 Try::Tiny 0 XSLoader 0 - base 0 integer 0 namespace::autoclean 0.19 overload 0 @@ -346,15 +352,15 @@ DISTRIBUTIONS parent 0 strict 0 warnings 0 - DateTime-Locale-1.36 - pathname: D/DR/DROLSKY/DateTime-Locale-1.36.tar.gz + DateTime-Locale-1.37 + pathname: D/DR/DROLSKY/DateTime-Locale-1.37.tar.gz provides: - DateTime::Locale 1.36 - DateTime::Locale::Base 1.36 - DateTime::Locale::Catalog 1.36 - DateTime::Locale::Data 1.36 - DateTime::Locale::FromData 1.36 - DateTime::Locale::Util 1.36 + DateTime::Locale 1.37 + DateTime::Locale::Base 1.37 + DateTime::Locale::Catalog 1.37 + DateTime::Locale::Data 1.37 + DateTime::Locale::FromData 1.37 + DateTime::Locale::Util 1.37 requirements: Carp 0 Dist::CheckConflicts 0.02 @@ -372,349 +378,349 @@ DISTRIBUTIONS perl 5.008004 strict 0 warnings 0 - DateTime-TimeZone-2.54 - pathname: D/DR/DROLSKY/DateTime-TimeZone-2.54.tar.gz - provides: - DateTime::TimeZone 2.54 - DateTime::TimeZone::Africa::Abidjan 2.54 - DateTime::TimeZone::Africa::Algiers 2.54 - DateTime::TimeZone::Africa::Bissau 2.54 - DateTime::TimeZone::Africa::Cairo 2.54 - DateTime::TimeZone::Africa::Casablanca 2.54 - DateTime::TimeZone::Africa::Ceuta 2.54 - DateTime::TimeZone::Africa::El_Aaiun 2.54 - DateTime::TimeZone::Africa::Johannesburg 2.54 - DateTime::TimeZone::Africa::Juba 2.54 - DateTime::TimeZone::Africa::Khartoum 2.54 - DateTime::TimeZone::Africa::Lagos 2.54 - DateTime::TimeZone::Africa::Maputo 2.54 - DateTime::TimeZone::Africa::Monrovia 2.54 - DateTime::TimeZone::Africa::Nairobi 2.54 - DateTime::TimeZone::Africa::Ndjamena 2.54 - DateTime::TimeZone::Africa::Sao_Tome 2.54 - DateTime::TimeZone::Africa::Tripoli 2.54 - DateTime::TimeZone::Africa::Tunis 2.54 - DateTime::TimeZone::Africa::Windhoek 2.54 - DateTime::TimeZone::America::Adak 2.54 - DateTime::TimeZone::America::Anchorage 2.54 - DateTime::TimeZone::America::Araguaina 2.54 - DateTime::TimeZone::America::Argentina::Buenos_Aires 2.54 - DateTime::TimeZone::America::Argentina::Catamarca 2.54 - DateTime::TimeZone::America::Argentina::Cordoba 2.54 - DateTime::TimeZone::America::Argentina::Jujuy 2.54 - DateTime::TimeZone::America::Argentina::La_Rioja 2.54 - DateTime::TimeZone::America::Argentina::Mendoza 2.54 - DateTime::TimeZone::America::Argentina::Rio_Gallegos 2.54 - DateTime::TimeZone::America::Argentina::Salta 2.54 - DateTime::TimeZone::America::Argentina::San_Juan 2.54 - DateTime::TimeZone::America::Argentina::San_Luis 2.54 - DateTime::TimeZone::America::Argentina::Tucuman 2.54 - DateTime::TimeZone::America::Argentina::Ushuaia 2.54 - DateTime::TimeZone::America::Asuncion 2.54 - DateTime::TimeZone::America::Bahia 2.54 - DateTime::TimeZone::America::Bahia_Banderas 2.54 - DateTime::TimeZone::America::Barbados 2.54 - DateTime::TimeZone::America::Belem 2.54 - DateTime::TimeZone::America::Belize 2.54 - DateTime::TimeZone::America::Boa_Vista 2.54 - DateTime::TimeZone::America::Bogota 2.54 - DateTime::TimeZone::America::Boise 2.54 - DateTime::TimeZone::America::Cambridge_Bay 2.54 - DateTime::TimeZone::America::Campo_Grande 2.54 - DateTime::TimeZone::America::Cancun 2.54 - DateTime::TimeZone::America::Caracas 2.54 - DateTime::TimeZone::America::Cayenne 2.54 - DateTime::TimeZone::America::Chicago 2.54 - DateTime::TimeZone::America::Chihuahua 2.54 - DateTime::TimeZone::America::Costa_Rica 2.54 - DateTime::TimeZone::America::Cuiaba 2.54 - DateTime::TimeZone::America::Danmarkshavn 2.54 - DateTime::TimeZone::America::Dawson 2.54 - DateTime::TimeZone::America::Dawson_Creek 2.54 - DateTime::TimeZone::America::Denver 2.54 - DateTime::TimeZone::America::Detroit 2.54 - DateTime::TimeZone::America::Edmonton 2.54 - DateTime::TimeZone::America::Eirunepe 2.54 - DateTime::TimeZone::America::El_Salvador 2.54 - DateTime::TimeZone::America::Fort_Nelson 2.54 - DateTime::TimeZone::America::Fortaleza 2.54 - DateTime::TimeZone::America::Glace_Bay 2.54 - DateTime::TimeZone::America::Goose_Bay 2.54 - DateTime::TimeZone::America::Grand_Turk 2.54 - DateTime::TimeZone::America::Guatemala 2.54 - DateTime::TimeZone::America::Guayaquil 2.54 - DateTime::TimeZone::America::Guyana 2.54 - DateTime::TimeZone::America::Halifax 2.54 - DateTime::TimeZone::America::Havana 2.54 - DateTime::TimeZone::America::Hermosillo 2.54 - DateTime::TimeZone::America::Indiana::Indianapolis 2.54 - DateTime::TimeZone::America::Indiana::Knox 2.54 - DateTime::TimeZone::America::Indiana::Marengo 2.54 - DateTime::TimeZone::America::Indiana::Petersburg 2.54 - DateTime::TimeZone::America::Indiana::Tell_City 2.54 - DateTime::TimeZone::America::Indiana::Vevay 2.54 - DateTime::TimeZone::America::Indiana::Vincennes 2.54 - DateTime::TimeZone::America::Indiana::Winamac 2.54 - DateTime::TimeZone::America::Inuvik 2.54 - DateTime::TimeZone::America::Iqaluit 2.54 - DateTime::TimeZone::America::Jamaica 2.54 - DateTime::TimeZone::America::Juneau 2.54 - DateTime::TimeZone::America::Kentucky::Louisville 2.54 - DateTime::TimeZone::America::Kentucky::Monticello 2.54 - DateTime::TimeZone::America::La_Paz 2.54 - DateTime::TimeZone::America::Lima 2.54 - DateTime::TimeZone::America::Los_Angeles 2.54 - DateTime::TimeZone::America::Maceio 2.54 - DateTime::TimeZone::America::Managua 2.54 - DateTime::TimeZone::America::Manaus 2.54 - DateTime::TimeZone::America::Martinique 2.54 - DateTime::TimeZone::America::Matamoros 2.54 - DateTime::TimeZone::America::Mazatlan 2.54 - DateTime::TimeZone::America::Menominee 2.54 - DateTime::TimeZone::America::Merida 2.54 - DateTime::TimeZone::America::Metlakatla 2.54 - DateTime::TimeZone::America::Mexico_City 2.54 - DateTime::TimeZone::America::Miquelon 2.54 - DateTime::TimeZone::America::Moncton 2.54 - DateTime::TimeZone::America::Monterrey 2.54 - DateTime::TimeZone::America::Montevideo 2.54 - DateTime::TimeZone::America::New_York 2.54 - DateTime::TimeZone::America::Nipigon 2.54 - DateTime::TimeZone::America::Nome 2.54 - DateTime::TimeZone::America::Noronha 2.54 - DateTime::TimeZone::America::North_Dakota::Beulah 2.54 - DateTime::TimeZone::America::North_Dakota::Center 2.54 - DateTime::TimeZone::America::North_Dakota::New_Salem 2.54 - DateTime::TimeZone::America::Nuuk 2.54 - DateTime::TimeZone::America::Ojinaga 2.54 - DateTime::TimeZone::America::Panama 2.54 - DateTime::TimeZone::America::Pangnirtung 2.54 - DateTime::TimeZone::America::Paramaribo 2.54 - DateTime::TimeZone::America::Phoenix 2.54 - DateTime::TimeZone::America::Port_au_Prince 2.54 - DateTime::TimeZone::America::Porto_Velho 2.54 - DateTime::TimeZone::America::Puerto_Rico 2.54 - DateTime::TimeZone::America::Punta_Arenas 2.54 - DateTime::TimeZone::America::Rainy_River 2.54 - DateTime::TimeZone::America::Rankin_Inlet 2.54 - DateTime::TimeZone::America::Recife 2.54 - DateTime::TimeZone::America::Regina 2.54 - DateTime::TimeZone::America::Resolute 2.54 - DateTime::TimeZone::America::Rio_Branco 2.54 - DateTime::TimeZone::America::Santarem 2.54 - DateTime::TimeZone::America::Santiago 2.54 - DateTime::TimeZone::America::Santo_Domingo 2.54 - DateTime::TimeZone::America::Sao_Paulo 2.54 - DateTime::TimeZone::America::Scoresbysund 2.54 - DateTime::TimeZone::America::Sitka 2.54 - DateTime::TimeZone::America::St_Johns 2.54 - DateTime::TimeZone::America::Swift_Current 2.54 - DateTime::TimeZone::America::Tegucigalpa 2.54 - DateTime::TimeZone::America::Thule 2.54 - DateTime::TimeZone::America::Thunder_Bay 2.54 - DateTime::TimeZone::America::Tijuana 2.54 - DateTime::TimeZone::America::Toronto 2.54 - DateTime::TimeZone::America::Vancouver 2.54 - DateTime::TimeZone::America::Whitehorse 2.54 - DateTime::TimeZone::America::Winnipeg 2.54 - DateTime::TimeZone::America::Yakutat 2.54 - DateTime::TimeZone::America::Yellowknife 2.54 - DateTime::TimeZone::Antarctica::Casey 2.54 - DateTime::TimeZone::Antarctica::Davis 2.54 - DateTime::TimeZone::Antarctica::Macquarie 2.54 - DateTime::TimeZone::Antarctica::Mawson 2.54 - DateTime::TimeZone::Antarctica::Palmer 2.54 - DateTime::TimeZone::Antarctica::Rothera 2.54 - DateTime::TimeZone::Antarctica::Troll 2.54 - DateTime::TimeZone::Asia::Almaty 2.54 - DateTime::TimeZone::Asia::Amman 2.54 - DateTime::TimeZone::Asia::Anadyr 2.54 - DateTime::TimeZone::Asia::Aqtau 2.54 - DateTime::TimeZone::Asia::Aqtobe 2.54 - DateTime::TimeZone::Asia::Ashgabat 2.54 - DateTime::TimeZone::Asia::Atyrau 2.54 - DateTime::TimeZone::Asia::Baghdad 2.54 - DateTime::TimeZone::Asia::Baku 2.54 - DateTime::TimeZone::Asia::Bangkok 2.54 - DateTime::TimeZone::Asia::Barnaul 2.54 - DateTime::TimeZone::Asia::Beirut 2.54 - DateTime::TimeZone::Asia::Bishkek 2.54 - DateTime::TimeZone::Asia::Chita 2.54 - DateTime::TimeZone::Asia::Choibalsan 2.54 - DateTime::TimeZone::Asia::Colombo 2.54 - DateTime::TimeZone::Asia::Damascus 2.54 - DateTime::TimeZone::Asia::Dhaka 2.54 - DateTime::TimeZone::Asia::Dili 2.54 - DateTime::TimeZone::Asia::Dubai 2.54 - DateTime::TimeZone::Asia::Dushanbe 2.54 - DateTime::TimeZone::Asia::Famagusta 2.54 - DateTime::TimeZone::Asia::Gaza 2.54 - DateTime::TimeZone::Asia::Hebron 2.54 - DateTime::TimeZone::Asia::Ho_Chi_Minh 2.54 - DateTime::TimeZone::Asia::Hong_Kong 2.54 - DateTime::TimeZone::Asia::Hovd 2.54 - DateTime::TimeZone::Asia::Irkutsk 2.54 - DateTime::TimeZone::Asia::Jakarta 2.54 - DateTime::TimeZone::Asia::Jayapura 2.54 - DateTime::TimeZone::Asia::Jerusalem 2.54 - DateTime::TimeZone::Asia::Kabul 2.54 - DateTime::TimeZone::Asia::Kamchatka 2.54 - DateTime::TimeZone::Asia::Karachi 2.54 - DateTime::TimeZone::Asia::Kathmandu 2.54 - DateTime::TimeZone::Asia::Khandyga 2.54 - DateTime::TimeZone::Asia::Kolkata 2.54 - DateTime::TimeZone::Asia::Krasnoyarsk 2.54 - DateTime::TimeZone::Asia::Kuching 2.54 - DateTime::TimeZone::Asia::Macau 2.54 - DateTime::TimeZone::Asia::Magadan 2.54 - DateTime::TimeZone::Asia::Makassar 2.54 - DateTime::TimeZone::Asia::Manila 2.54 - DateTime::TimeZone::Asia::Nicosia 2.54 - DateTime::TimeZone::Asia::Novokuznetsk 2.54 - DateTime::TimeZone::Asia::Novosibirsk 2.54 - DateTime::TimeZone::Asia::Omsk 2.54 - DateTime::TimeZone::Asia::Oral 2.54 - DateTime::TimeZone::Asia::Pontianak 2.54 - DateTime::TimeZone::Asia::Pyongyang 2.54 - DateTime::TimeZone::Asia::Qatar 2.54 - DateTime::TimeZone::Asia::Qostanay 2.54 - DateTime::TimeZone::Asia::Qyzylorda 2.54 - DateTime::TimeZone::Asia::Riyadh 2.54 - DateTime::TimeZone::Asia::Sakhalin 2.54 - DateTime::TimeZone::Asia::Samarkand 2.54 - DateTime::TimeZone::Asia::Seoul 2.54 - DateTime::TimeZone::Asia::Shanghai 2.54 - DateTime::TimeZone::Asia::Singapore 2.54 - DateTime::TimeZone::Asia::Srednekolymsk 2.54 - DateTime::TimeZone::Asia::Taipei 2.54 - DateTime::TimeZone::Asia::Tashkent 2.54 - DateTime::TimeZone::Asia::Tbilisi 2.54 - DateTime::TimeZone::Asia::Tehran 2.54 - DateTime::TimeZone::Asia::Thimphu 2.54 - DateTime::TimeZone::Asia::Tokyo 2.54 - DateTime::TimeZone::Asia::Tomsk 2.54 - DateTime::TimeZone::Asia::Ulaanbaatar 2.54 - DateTime::TimeZone::Asia::Urumqi 2.54 - DateTime::TimeZone::Asia::Ust_Nera 2.54 - DateTime::TimeZone::Asia::Vladivostok 2.54 - DateTime::TimeZone::Asia::Yakutsk 2.54 - DateTime::TimeZone::Asia::Yangon 2.54 - DateTime::TimeZone::Asia::Yekaterinburg 2.54 - DateTime::TimeZone::Asia::Yerevan 2.54 - DateTime::TimeZone::Atlantic::Azores 2.54 - DateTime::TimeZone::Atlantic::Bermuda 2.54 - DateTime::TimeZone::Atlantic::Canary 2.54 - DateTime::TimeZone::Atlantic::Cape_Verde 2.54 - DateTime::TimeZone::Atlantic::Faroe 2.54 - DateTime::TimeZone::Atlantic::Madeira 2.54 - DateTime::TimeZone::Atlantic::South_Georgia 2.54 - DateTime::TimeZone::Atlantic::Stanley 2.54 - DateTime::TimeZone::Australia::Adelaide 2.54 - DateTime::TimeZone::Australia::Brisbane 2.54 - DateTime::TimeZone::Australia::Broken_Hill 2.54 - DateTime::TimeZone::Australia::Darwin 2.54 - DateTime::TimeZone::Australia::Eucla 2.54 - DateTime::TimeZone::Australia::Hobart 2.54 - DateTime::TimeZone::Australia::Lindeman 2.54 - DateTime::TimeZone::Australia::Lord_Howe 2.54 - DateTime::TimeZone::Australia::Melbourne 2.54 - DateTime::TimeZone::Australia::Perth 2.54 - DateTime::TimeZone::Australia::Sydney 2.54 - DateTime::TimeZone::CET 2.54 - DateTime::TimeZone::CST6CDT 2.54 - DateTime::TimeZone::Catalog 2.54 - DateTime::TimeZone::EET 2.54 - DateTime::TimeZone::EST 2.54 - DateTime::TimeZone::EST5EDT 2.54 - DateTime::TimeZone::Europe::Andorra 2.54 - DateTime::TimeZone::Europe::Astrakhan 2.54 - DateTime::TimeZone::Europe::Athens 2.54 - DateTime::TimeZone::Europe::Belgrade 2.54 - DateTime::TimeZone::Europe::Berlin 2.54 - DateTime::TimeZone::Europe::Brussels 2.54 - DateTime::TimeZone::Europe::Bucharest 2.54 - DateTime::TimeZone::Europe::Budapest 2.54 - DateTime::TimeZone::Europe::Chisinau 2.54 - DateTime::TimeZone::Europe::Dublin 2.54 - DateTime::TimeZone::Europe::Gibraltar 2.54 - DateTime::TimeZone::Europe::Helsinki 2.54 - DateTime::TimeZone::Europe::Istanbul 2.54 - DateTime::TimeZone::Europe::Kaliningrad 2.54 - DateTime::TimeZone::Europe::Kirov 2.54 - DateTime::TimeZone::Europe::Kyiv 2.54 - DateTime::TimeZone::Europe::Lisbon 2.54 - DateTime::TimeZone::Europe::London 2.54 - DateTime::TimeZone::Europe::Madrid 2.54 - DateTime::TimeZone::Europe::Malta 2.54 - DateTime::TimeZone::Europe::Minsk 2.54 - DateTime::TimeZone::Europe::Moscow 2.54 - DateTime::TimeZone::Europe::Paris 2.54 - DateTime::TimeZone::Europe::Prague 2.54 - DateTime::TimeZone::Europe::Riga 2.54 - DateTime::TimeZone::Europe::Rome 2.54 - DateTime::TimeZone::Europe::Samara 2.54 - DateTime::TimeZone::Europe::Saratov 2.54 - DateTime::TimeZone::Europe::Simferopol 2.54 - DateTime::TimeZone::Europe::Sofia 2.54 - DateTime::TimeZone::Europe::Tallinn 2.54 - DateTime::TimeZone::Europe::Tirane 2.54 - DateTime::TimeZone::Europe::Ulyanovsk 2.54 - DateTime::TimeZone::Europe::Vienna 2.54 - DateTime::TimeZone::Europe::Vilnius 2.54 - DateTime::TimeZone::Europe::Volgograd 2.54 - DateTime::TimeZone::Europe::Warsaw 2.54 - DateTime::TimeZone::Europe::Zurich 2.54 - DateTime::TimeZone::Floating 2.54 - DateTime::TimeZone::HST 2.54 - DateTime::TimeZone::Indian::Chagos 2.54 - DateTime::TimeZone::Indian::Maldives 2.54 - DateTime::TimeZone::Indian::Mauritius 2.54 - DateTime::TimeZone::Local 2.54 - DateTime::TimeZone::Local::Android 2.54 - DateTime::TimeZone::Local::Unix 2.54 - DateTime::TimeZone::Local::VMS 2.54 - DateTime::TimeZone::MET 2.54 - DateTime::TimeZone::MST 2.54 - DateTime::TimeZone::MST7MDT 2.54 - DateTime::TimeZone::OffsetOnly 2.54 - DateTime::TimeZone::OlsonDB 2.54 - DateTime::TimeZone::OlsonDB::Change 2.54 - DateTime::TimeZone::OlsonDB::Observance 2.54 - DateTime::TimeZone::OlsonDB::Rule 2.54 - DateTime::TimeZone::OlsonDB::Zone 2.54 - DateTime::TimeZone::PST8PDT 2.54 - DateTime::TimeZone::Pacific::Apia 2.54 - DateTime::TimeZone::Pacific::Auckland 2.54 - DateTime::TimeZone::Pacific::Bougainville 2.54 - DateTime::TimeZone::Pacific::Chatham 2.54 - DateTime::TimeZone::Pacific::Easter 2.54 - DateTime::TimeZone::Pacific::Efate 2.54 - DateTime::TimeZone::Pacific::Fakaofo 2.54 - DateTime::TimeZone::Pacific::Fiji 2.54 - DateTime::TimeZone::Pacific::Galapagos 2.54 - DateTime::TimeZone::Pacific::Gambier 2.54 - DateTime::TimeZone::Pacific::Guadalcanal 2.54 - DateTime::TimeZone::Pacific::Guam 2.54 - DateTime::TimeZone::Pacific::Honolulu 2.54 - DateTime::TimeZone::Pacific::Kanton 2.54 - DateTime::TimeZone::Pacific::Kiritimati 2.54 - DateTime::TimeZone::Pacific::Kosrae 2.54 - DateTime::TimeZone::Pacific::Kwajalein 2.54 - DateTime::TimeZone::Pacific::Marquesas 2.54 - DateTime::TimeZone::Pacific::Nauru 2.54 - DateTime::TimeZone::Pacific::Niue 2.54 - DateTime::TimeZone::Pacific::Norfolk 2.54 - DateTime::TimeZone::Pacific::Noumea 2.54 - DateTime::TimeZone::Pacific::Pago_Pago 2.54 - DateTime::TimeZone::Pacific::Palau 2.54 - DateTime::TimeZone::Pacific::Pitcairn 2.54 - DateTime::TimeZone::Pacific::Port_Moresby 2.54 - DateTime::TimeZone::Pacific::Rarotonga 2.54 - DateTime::TimeZone::Pacific::Tahiti 2.54 - DateTime::TimeZone::Pacific::Tarawa 2.54 - DateTime::TimeZone::Pacific::Tongatapu 2.54 - DateTime::TimeZone::UTC 2.54 - DateTime::TimeZone::WET 2.54 + DateTime-TimeZone-2.55 + pathname: D/DR/DROLSKY/DateTime-TimeZone-2.55.tar.gz + provides: + DateTime::TimeZone 2.55 + DateTime::TimeZone::Africa::Abidjan 2.55 + DateTime::TimeZone::Africa::Algiers 2.55 + DateTime::TimeZone::Africa::Bissau 2.55 + DateTime::TimeZone::Africa::Cairo 2.55 + DateTime::TimeZone::Africa::Casablanca 2.55 + DateTime::TimeZone::Africa::Ceuta 2.55 + DateTime::TimeZone::Africa::El_Aaiun 2.55 + DateTime::TimeZone::Africa::Johannesburg 2.55 + DateTime::TimeZone::Africa::Juba 2.55 + DateTime::TimeZone::Africa::Khartoum 2.55 + DateTime::TimeZone::Africa::Lagos 2.55 + DateTime::TimeZone::Africa::Maputo 2.55 + DateTime::TimeZone::Africa::Monrovia 2.55 + DateTime::TimeZone::Africa::Nairobi 2.55 + DateTime::TimeZone::Africa::Ndjamena 2.55 + DateTime::TimeZone::Africa::Sao_Tome 2.55 + DateTime::TimeZone::Africa::Tripoli 2.55 + DateTime::TimeZone::Africa::Tunis 2.55 + DateTime::TimeZone::Africa::Windhoek 2.55 + DateTime::TimeZone::America::Adak 2.55 + DateTime::TimeZone::America::Anchorage 2.55 + DateTime::TimeZone::America::Araguaina 2.55 + DateTime::TimeZone::America::Argentina::Buenos_Aires 2.55 + DateTime::TimeZone::America::Argentina::Catamarca 2.55 + DateTime::TimeZone::America::Argentina::Cordoba 2.55 + DateTime::TimeZone::America::Argentina::Jujuy 2.55 + DateTime::TimeZone::America::Argentina::La_Rioja 2.55 + DateTime::TimeZone::America::Argentina::Mendoza 2.55 + DateTime::TimeZone::America::Argentina::Rio_Gallegos 2.55 + DateTime::TimeZone::America::Argentina::Salta 2.55 + DateTime::TimeZone::America::Argentina::San_Juan 2.55 + DateTime::TimeZone::America::Argentina::San_Luis 2.55 + DateTime::TimeZone::America::Argentina::Tucuman 2.55 + DateTime::TimeZone::America::Argentina::Ushuaia 2.55 + DateTime::TimeZone::America::Asuncion 2.55 + DateTime::TimeZone::America::Bahia 2.55 + DateTime::TimeZone::America::Bahia_Banderas 2.55 + DateTime::TimeZone::America::Barbados 2.55 + DateTime::TimeZone::America::Belem 2.55 + DateTime::TimeZone::America::Belize 2.55 + DateTime::TimeZone::America::Boa_Vista 2.55 + DateTime::TimeZone::America::Bogota 2.55 + DateTime::TimeZone::America::Boise 2.55 + DateTime::TimeZone::America::Cambridge_Bay 2.55 + DateTime::TimeZone::America::Campo_Grande 2.55 + DateTime::TimeZone::America::Cancun 2.55 + DateTime::TimeZone::America::Caracas 2.55 + DateTime::TimeZone::America::Cayenne 2.55 + DateTime::TimeZone::America::Chicago 2.55 + DateTime::TimeZone::America::Chihuahua 2.55 + DateTime::TimeZone::America::Costa_Rica 2.55 + DateTime::TimeZone::America::Cuiaba 2.55 + DateTime::TimeZone::America::Danmarkshavn 2.55 + DateTime::TimeZone::America::Dawson 2.55 + DateTime::TimeZone::America::Dawson_Creek 2.55 + DateTime::TimeZone::America::Denver 2.55 + DateTime::TimeZone::America::Detroit 2.55 + DateTime::TimeZone::America::Edmonton 2.55 + DateTime::TimeZone::America::Eirunepe 2.55 + DateTime::TimeZone::America::El_Salvador 2.55 + DateTime::TimeZone::America::Fort_Nelson 2.55 + DateTime::TimeZone::America::Fortaleza 2.55 + DateTime::TimeZone::America::Glace_Bay 2.55 + DateTime::TimeZone::America::Goose_Bay 2.55 + DateTime::TimeZone::America::Grand_Turk 2.55 + DateTime::TimeZone::America::Guatemala 2.55 + DateTime::TimeZone::America::Guayaquil 2.55 + DateTime::TimeZone::America::Guyana 2.55 + DateTime::TimeZone::America::Halifax 2.55 + DateTime::TimeZone::America::Havana 2.55 + DateTime::TimeZone::America::Hermosillo 2.55 + DateTime::TimeZone::America::Indiana::Indianapolis 2.55 + DateTime::TimeZone::America::Indiana::Knox 2.55 + DateTime::TimeZone::America::Indiana::Marengo 2.55 + DateTime::TimeZone::America::Indiana::Petersburg 2.55 + DateTime::TimeZone::America::Indiana::Tell_City 2.55 + DateTime::TimeZone::America::Indiana::Vevay 2.55 + DateTime::TimeZone::America::Indiana::Vincennes 2.55 + DateTime::TimeZone::America::Indiana::Winamac 2.55 + DateTime::TimeZone::America::Inuvik 2.55 + DateTime::TimeZone::America::Iqaluit 2.55 + DateTime::TimeZone::America::Jamaica 2.55 + DateTime::TimeZone::America::Juneau 2.55 + DateTime::TimeZone::America::Kentucky::Louisville 2.55 + DateTime::TimeZone::America::Kentucky::Monticello 2.55 + DateTime::TimeZone::America::La_Paz 2.55 + DateTime::TimeZone::America::Lima 2.55 + DateTime::TimeZone::America::Los_Angeles 2.55 + DateTime::TimeZone::America::Maceio 2.55 + DateTime::TimeZone::America::Managua 2.55 + DateTime::TimeZone::America::Manaus 2.55 + DateTime::TimeZone::America::Martinique 2.55 + DateTime::TimeZone::America::Matamoros 2.55 + DateTime::TimeZone::America::Mazatlan 2.55 + DateTime::TimeZone::America::Menominee 2.55 + DateTime::TimeZone::America::Merida 2.55 + DateTime::TimeZone::America::Metlakatla 2.55 + DateTime::TimeZone::America::Mexico_City 2.55 + DateTime::TimeZone::America::Miquelon 2.55 + DateTime::TimeZone::America::Moncton 2.55 + DateTime::TimeZone::America::Monterrey 2.55 + DateTime::TimeZone::America::Montevideo 2.55 + DateTime::TimeZone::America::New_York 2.55 + DateTime::TimeZone::America::Nipigon 2.55 + DateTime::TimeZone::America::Nome 2.55 + DateTime::TimeZone::America::Noronha 2.55 + DateTime::TimeZone::America::North_Dakota::Beulah 2.55 + DateTime::TimeZone::America::North_Dakota::Center 2.55 + DateTime::TimeZone::America::North_Dakota::New_Salem 2.55 + DateTime::TimeZone::America::Nuuk 2.55 + DateTime::TimeZone::America::Ojinaga 2.55 + DateTime::TimeZone::America::Panama 2.55 + DateTime::TimeZone::America::Pangnirtung 2.55 + DateTime::TimeZone::America::Paramaribo 2.55 + DateTime::TimeZone::America::Phoenix 2.55 + DateTime::TimeZone::America::Port_au_Prince 2.55 + DateTime::TimeZone::America::Porto_Velho 2.55 + DateTime::TimeZone::America::Puerto_Rico 2.55 + DateTime::TimeZone::America::Punta_Arenas 2.55 + DateTime::TimeZone::America::Rainy_River 2.55 + DateTime::TimeZone::America::Rankin_Inlet 2.55 + DateTime::TimeZone::America::Recife 2.55 + DateTime::TimeZone::America::Regina 2.55 + DateTime::TimeZone::America::Resolute 2.55 + DateTime::TimeZone::America::Rio_Branco 2.55 + DateTime::TimeZone::America::Santarem 2.55 + DateTime::TimeZone::America::Santiago 2.55 + DateTime::TimeZone::America::Santo_Domingo 2.55 + DateTime::TimeZone::America::Sao_Paulo 2.55 + DateTime::TimeZone::America::Scoresbysund 2.55 + DateTime::TimeZone::America::Sitka 2.55 + DateTime::TimeZone::America::St_Johns 2.55 + DateTime::TimeZone::America::Swift_Current 2.55 + DateTime::TimeZone::America::Tegucigalpa 2.55 + DateTime::TimeZone::America::Thule 2.55 + DateTime::TimeZone::America::Thunder_Bay 2.55 + DateTime::TimeZone::America::Tijuana 2.55 + DateTime::TimeZone::America::Toronto 2.55 + DateTime::TimeZone::America::Vancouver 2.55 + DateTime::TimeZone::America::Whitehorse 2.55 + DateTime::TimeZone::America::Winnipeg 2.55 + DateTime::TimeZone::America::Yakutat 2.55 + DateTime::TimeZone::America::Yellowknife 2.55 + DateTime::TimeZone::Antarctica::Casey 2.55 + DateTime::TimeZone::Antarctica::Davis 2.55 + DateTime::TimeZone::Antarctica::Macquarie 2.55 + DateTime::TimeZone::Antarctica::Mawson 2.55 + DateTime::TimeZone::Antarctica::Palmer 2.55 + DateTime::TimeZone::Antarctica::Rothera 2.55 + DateTime::TimeZone::Antarctica::Troll 2.55 + DateTime::TimeZone::Asia::Almaty 2.55 + DateTime::TimeZone::Asia::Amman 2.55 + DateTime::TimeZone::Asia::Anadyr 2.55 + DateTime::TimeZone::Asia::Aqtau 2.55 + DateTime::TimeZone::Asia::Aqtobe 2.55 + DateTime::TimeZone::Asia::Ashgabat 2.55 + DateTime::TimeZone::Asia::Atyrau 2.55 + DateTime::TimeZone::Asia::Baghdad 2.55 + DateTime::TimeZone::Asia::Baku 2.55 + DateTime::TimeZone::Asia::Bangkok 2.55 + DateTime::TimeZone::Asia::Barnaul 2.55 + DateTime::TimeZone::Asia::Beirut 2.55 + DateTime::TimeZone::Asia::Bishkek 2.55 + DateTime::TimeZone::Asia::Chita 2.55 + DateTime::TimeZone::Asia::Choibalsan 2.55 + DateTime::TimeZone::Asia::Colombo 2.55 + DateTime::TimeZone::Asia::Damascus 2.55 + DateTime::TimeZone::Asia::Dhaka 2.55 + DateTime::TimeZone::Asia::Dili 2.55 + DateTime::TimeZone::Asia::Dubai 2.55 + DateTime::TimeZone::Asia::Dushanbe 2.55 + DateTime::TimeZone::Asia::Famagusta 2.55 + DateTime::TimeZone::Asia::Gaza 2.55 + DateTime::TimeZone::Asia::Hebron 2.55 + DateTime::TimeZone::Asia::Ho_Chi_Minh 2.55 + DateTime::TimeZone::Asia::Hong_Kong 2.55 + DateTime::TimeZone::Asia::Hovd 2.55 + DateTime::TimeZone::Asia::Irkutsk 2.55 + DateTime::TimeZone::Asia::Jakarta 2.55 + DateTime::TimeZone::Asia::Jayapura 2.55 + DateTime::TimeZone::Asia::Jerusalem 2.55 + DateTime::TimeZone::Asia::Kabul 2.55 + DateTime::TimeZone::Asia::Kamchatka 2.55 + DateTime::TimeZone::Asia::Karachi 2.55 + DateTime::TimeZone::Asia::Kathmandu 2.55 + DateTime::TimeZone::Asia::Khandyga 2.55 + DateTime::TimeZone::Asia::Kolkata 2.55 + DateTime::TimeZone::Asia::Krasnoyarsk 2.55 + DateTime::TimeZone::Asia::Kuching 2.55 + DateTime::TimeZone::Asia::Macau 2.55 + DateTime::TimeZone::Asia::Magadan 2.55 + DateTime::TimeZone::Asia::Makassar 2.55 + DateTime::TimeZone::Asia::Manila 2.55 + DateTime::TimeZone::Asia::Nicosia 2.55 + DateTime::TimeZone::Asia::Novokuznetsk 2.55 + DateTime::TimeZone::Asia::Novosibirsk 2.55 + DateTime::TimeZone::Asia::Omsk 2.55 + DateTime::TimeZone::Asia::Oral 2.55 + DateTime::TimeZone::Asia::Pontianak 2.55 + DateTime::TimeZone::Asia::Pyongyang 2.55 + DateTime::TimeZone::Asia::Qatar 2.55 + DateTime::TimeZone::Asia::Qostanay 2.55 + DateTime::TimeZone::Asia::Qyzylorda 2.55 + DateTime::TimeZone::Asia::Riyadh 2.55 + DateTime::TimeZone::Asia::Sakhalin 2.55 + DateTime::TimeZone::Asia::Samarkand 2.55 + DateTime::TimeZone::Asia::Seoul 2.55 + DateTime::TimeZone::Asia::Shanghai 2.55 + DateTime::TimeZone::Asia::Singapore 2.55 + DateTime::TimeZone::Asia::Srednekolymsk 2.55 + DateTime::TimeZone::Asia::Taipei 2.55 + DateTime::TimeZone::Asia::Tashkent 2.55 + DateTime::TimeZone::Asia::Tbilisi 2.55 + DateTime::TimeZone::Asia::Tehran 2.55 + DateTime::TimeZone::Asia::Thimphu 2.55 + DateTime::TimeZone::Asia::Tokyo 2.55 + DateTime::TimeZone::Asia::Tomsk 2.55 + DateTime::TimeZone::Asia::Ulaanbaatar 2.55 + DateTime::TimeZone::Asia::Urumqi 2.55 + DateTime::TimeZone::Asia::Ust_Nera 2.55 + DateTime::TimeZone::Asia::Vladivostok 2.55 + DateTime::TimeZone::Asia::Yakutsk 2.55 + DateTime::TimeZone::Asia::Yangon 2.55 + DateTime::TimeZone::Asia::Yekaterinburg 2.55 + DateTime::TimeZone::Asia::Yerevan 2.55 + DateTime::TimeZone::Atlantic::Azores 2.55 + DateTime::TimeZone::Atlantic::Bermuda 2.55 + DateTime::TimeZone::Atlantic::Canary 2.55 + DateTime::TimeZone::Atlantic::Cape_Verde 2.55 + DateTime::TimeZone::Atlantic::Faroe 2.55 + DateTime::TimeZone::Atlantic::Madeira 2.55 + DateTime::TimeZone::Atlantic::South_Georgia 2.55 + DateTime::TimeZone::Atlantic::Stanley 2.55 + DateTime::TimeZone::Australia::Adelaide 2.55 + DateTime::TimeZone::Australia::Brisbane 2.55 + DateTime::TimeZone::Australia::Broken_Hill 2.55 + DateTime::TimeZone::Australia::Darwin 2.55 + DateTime::TimeZone::Australia::Eucla 2.55 + DateTime::TimeZone::Australia::Hobart 2.55 + DateTime::TimeZone::Australia::Lindeman 2.55 + DateTime::TimeZone::Australia::Lord_Howe 2.55 + DateTime::TimeZone::Australia::Melbourne 2.55 + DateTime::TimeZone::Australia::Perth 2.55 + DateTime::TimeZone::Australia::Sydney 2.55 + DateTime::TimeZone::CET 2.55 + DateTime::TimeZone::CST6CDT 2.55 + DateTime::TimeZone::Catalog 2.55 + DateTime::TimeZone::EET 2.55 + DateTime::TimeZone::EST 2.55 + DateTime::TimeZone::EST5EDT 2.55 + DateTime::TimeZone::Europe::Andorra 2.55 + DateTime::TimeZone::Europe::Astrakhan 2.55 + DateTime::TimeZone::Europe::Athens 2.55 + DateTime::TimeZone::Europe::Belgrade 2.55 + DateTime::TimeZone::Europe::Berlin 2.55 + DateTime::TimeZone::Europe::Brussels 2.55 + DateTime::TimeZone::Europe::Bucharest 2.55 + DateTime::TimeZone::Europe::Budapest 2.55 + DateTime::TimeZone::Europe::Chisinau 2.55 + DateTime::TimeZone::Europe::Dublin 2.55 + DateTime::TimeZone::Europe::Gibraltar 2.55 + DateTime::TimeZone::Europe::Helsinki 2.55 + DateTime::TimeZone::Europe::Istanbul 2.55 + DateTime::TimeZone::Europe::Kaliningrad 2.55 + DateTime::TimeZone::Europe::Kirov 2.55 + DateTime::TimeZone::Europe::Kyiv 2.55 + DateTime::TimeZone::Europe::Lisbon 2.55 + DateTime::TimeZone::Europe::London 2.55 + DateTime::TimeZone::Europe::Madrid 2.55 + DateTime::TimeZone::Europe::Malta 2.55 + DateTime::TimeZone::Europe::Minsk 2.55 + DateTime::TimeZone::Europe::Moscow 2.55 + DateTime::TimeZone::Europe::Paris 2.55 + DateTime::TimeZone::Europe::Prague 2.55 + DateTime::TimeZone::Europe::Riga 2.55 + DateTime::TimeZone::Europe::Rome 2.55 + DateTime::TimeZone::Europe::Samara 2.55 + DateTime::TimeZone::Europe::Saratov 2.55 + DateTime::TimeZone::Europe::Simferopol 2.55 + DateTime::TimeZone::Europe::Sofia 2.55 + DateTime::TimeZone::Europe::Tallinn 2.55 + DateTime::TimeZone::Europe::Tirane 2.55 + DateTime::TimeZone::Europe::Ulyanovsk 2.55 + DateTime::TimeZone::Europe::Vienna 2.55 + DateTime::TimeZone::Europe::Vilnius 2.55 + DateTime::TimeZone::Europe::Volgograd 2.55 + DateTime::TimeZone::Europe::Warsaw 2.55 + DateTime::TimeZone::Europe::Zurich 2.55 + DateTime::TimeZone::Floating 2.55 + DateTime::TimeZone::HST 2.55 + DateTime::TimeZone::Indian::Chagos 2.55 + DateTime::TimeZone::Indian::Maldives 2.55 + DateTime::TimeZone::Indian::Mauritius 2.55 + DateTime::TimeZone::Local 2.55 + DateTime::TimeZone::Local::Android 2.55 + DateTime::TimeZone::Local::Unix 2.55 + DateTime::TimeZone::Local::VMS 2.55 + DateTime::TimeZone::MET 2.55 + DateTime::TimeZone::MST 2.55 + DateTime::TimeZone::MST7MDT 2.55 + DateTime::TimeZone::OffsetOnly 2.55 + DateTime::TimeZone::OlsonDB 2.55 + DateTime::TimeZone::OlsonDB::Change 2.55 + DateTime::TimeZone::OlsonDB::Observance 2.55 + DateTime::TimeZone::OlsonDB::Rule 2.55 + DateTime::TimeZone::OlsonDB::Zone 2.55 + DateTime::TimeZone::PST8PDT 2.55 + DateTime::TimeZone::Pacific::Apia 2.55 + DateTime::TimeZone::Pacific::Auckland 2.55 + DateTime::TimeZone::Pacific::Bougainville 2.55 + DateTime::TimeZone::Pacific::Chatham 2.55 + DateTime::TimeZone::Pacific::Easter 2.55 + DateTime::TimeZone::Pacific::Efate 2.55 + DateTime::TimeZone::Pacific::Fakaofo 2.55 + DateTime::TimeZone::Pacific::Fiji 2.55 + DateTime::TimeZone::Pacific::Galapagos 2.55 + DateTime::TimeZone::Pacific::Gambier 2.55 + DateTime::TimeZone::Pacific::Guadalcanal 2.55 + DateTime::TimeZone::Pacific::Guam 2.55 + DateTime::TimeZone::Pacific::Honolulu 2.55 + DateTime::TimeZone::Pacific::Kanton 2.55 + DateTime::TimeZone::Pacific::Kiritimati 2.55 + DateTime::TimeZone::Pacific::Kosrae 2.55 + DateTime::TimeZone::Pacific::Kwajalein 2.55 + DateTime::TimeZone::Pacific::Marquesas 2.55 + DateTime::TimeZone::Pacific::Nauru 2.55 + DateTime::TimeZone::Pacific::Niue 2.55 + DateTime::TimeZone::Pacific::Norfolk 2.55 + DateTime::TimeZone::Pacific::Noumea 2.55 + DateTime::TimeZone::Pacific::Pago_Pago 2.55 + DateTime::TimeZone::Pacific::Palau 2.55 + DateTime::TimeZone::Pacific::Pitcairn 2.55 + DateTime::TimeZone::Pacific::Port_Moresby 2.55 + DateTime::TimeZone::Pacific::Rarotonga 2.55 + DateTime::TimeZone::Pacific::Tahiti 2.55 + DateTime::TimeZone::Pacific::Tarawa 2.55 + DateTime::TimeZone::Pacific::Tongatapu 2.55 + DateTime::TimeZone::UTC 2.55 + DateTime::TimeZone::WET 2.55 requirements: Class::Singleton 1.03 Cwd 3 @@ -798,11 +804,11 @@ DISTRIBUTIONS perl 5.008001 strict 0 warnings 0 - Exporter-Tiny-1.004003 - pathname: T/TO/TOBYINK/Exporter-Tiny-1.004003.tar.gz + Exporter-Tiny-1.004004 + pathname: T/TO/TOBYINK/Exporter-Tiny-1.004004.tar.gz provides: - Exporter::Shiny 1.004003 - Exporter::Tiny 1.004003 + Exporter::Shiny 1.004004 + Exporter::Tiny 1.004004 requirements: ExtUtils::MakeMaker 6.17 perl 5.006001 @@ -993,16 +999,16 @@ DISTRIBUTIONS parent 0 perl 5.008001 strictures 2.000000 - HTML-Parser-3.78 - pathname: O/OA/OALDERS/HTML-Parser-3.78.tar.gz + HTML-Parser-3.79 + pathname: O/OA/OALDERS/HTML-Parser-3.79.tar.gz provides: - HTML::Entities 3.78 - HTML::Filter 3.78 - HTML::HeadParser 3.78 - HTML::LinkExtor 3.78 - HTML::Parser 3.78 - HTML::PullParser 3.78 - HTML::TokeParser 3.78 + HTML::Entities 3.79 + HTML::Filter 3.79 + HTML::HeadParser 3.79 + HTML::LinkExtor 3.79 + HTML::Parser 3.79 + HTML::PullParser 3.79 + HTML::TokeParser 3.79 requirements: Carp 0 Exporter 0 @@ -1046,22 +1052,24 @@ DISTRIBUTIONS Time::Zone 0 perl 5.006002 strict 0 - HTTP-Message-6.37 - pathname: O/OA/OALDERS/HTTP-Message-6.37.tar.gz - provides: - HTTP::Config 6.37 - HTTP::Headers 6.37 - HTTP::Headers::Auth 6.37 - HTTP::Headers::ETag 6.37 - HTTP::Headers::Util 6.37 - HTTP::Message 6.37 - HTTP::Request 6.37 - HTTP::Request::Common 6.37 - HTTP::Response 6.37 - HTTP::Status 6.37 + HTTP-Message-6.44 + pathname: O/OA/OALDERS/HTTP-Message-6.44.tar.gz + provides: + HTTP::Config 6.44 + HTTP::Headers 6.44 + HTTP::Headers::Auth 6.44 + HTTP::Headers::ETag 6.44 + HTTP::Headers::Util 6.44 + HTTP::Message 6.44 + HTTP::Request 6.44 + HTTP::Request::Common 6.44 + HTTP::Response 6.44 + HTTP::Status 6.44 requirements: Carp 0 - Compress::Raw::Zlib 0 + Clone 0.46 + Compress::Raw::Bzip2 0 + Compress::Raw::Zlib 2.062 Encode 3.01 Encode::Locale 1 Exporter 5.57 @@ -1072,15 +1080,13 @@ DISTRIBUTIONS IO::Compress::Deflate 0 IO::Compress::Gzip 0 IO::HTML 0 - IO::Uncompress::Bunzip2 2.021 - IO::Uncompress::Gunzip 0 IO::Uncompress::Inflate 0 IO::Uncompress::RawInflate 0 LWP::MediaTypes 6 MIME::Base64 2.1 MIME::QuotedPrint 0 URI 1.10 - base 0 + parent 0 perl 5.008001 strict 0 warnings 0 @@ -1142,11 +1148,11 @@ DISTRIBUTIONS IO::String 1.08 requirements: ExtUtils::MakeMaker 0 - JSON-4.09 - pathname: I/IS/ISHIGAKI/JSON-4.09.tar.gz + JSON-4.10 + pathname: I/IS/ISHIGAKI/JSON-4.10.tar.gz provides: - JSON 4.09 - JSON::Backend::PP 4.09 + JSON 4.10 + JSON::Backend::PP 4.10 requirements: ExtUtils::MakeMaker 0 Test::More 0 @@ -1327,8 +1333,8 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Mojolicious-9.27 - pathname: S/SR/SRI/Mojolicious-9.27.tar.gz + Mojolicious-9.28 + pathname: S/SR/SRI/Mojolicious-9.28.tar.gz provides: Mojo undef Mojo::Asset undef @@ -1396,7 +1402,7 @@ DISTRIBUTIONS Mojo::UserAgent::Transactor undef Mojo::Util undef Mojo::WebSocket undef - Mojolicious 9.27 + Mojolicious 9.28 Mojolicious::Command undef Mojolicious::Command::Author::cpanify undef Mojolicious::Command::Author::generate undef @@ -1547,11 +1553,11 @@ DISTRIBUTIONS overload 0 strict 0 warnings 0 - Path-Tiny-0.124 - pathname: D/DA/DAGOLDEN/Path-Tiny-0.124.tar.gz + Path-Tiny-0.130 + pathname: D/DA/DAGOLDEN/Path-Tiny-0.130.tar.gz provides: - Path::Tiny 0.124 - Path::Tiny::Error 0.124 + Path::Tiny 0.130 + Path::Tiny::Error 0.130 requirements: Carp 0 Cwd 0 @@ -1561,6 +1567,7 @@ DISTRIBUTIONS Exporter 5.57 ExtUtils::MakeMaker 6.17 Fcntl 0 + File::Compare 0 File::Copy 0 File::Glob 0 File::Path 2.07 @@ -1828,6 +1835,30 @@ DISTRIBUTIONS Test::Pod 0 Travel::Status::DE::IRIS 1.2 perl v5.20.0 + Travel-Status-DE-DeutscheBahn-4.00 + pathname: D/DE/DERF/Travel-Status-DE-DeutscheBahn-4.00.tar.gz + provides: + Travel::Status::DE::DeutscheBahn 4.00 + Travel::Status::DE::HAFAS 4.00 + Travel::Status::DE::HAFAS::Journey 4.00 + Travel::Status::DE::HAFAS::Message 4.00 + Travel::Status::DE::HAFAS::Polyline 0.06 + Travel::Status::DE::HAFAS::StopFinder 4.00 + requirements: + Carp 0 + Class::Accessor 0.16 + DateTime 0 + DateTime::Format::Strptime 0 + Digest::MD5 0 + Getopt::Long 0 + JSON 0 + LWP::Protocol::https 0 + LWP::UserAgent 0 + Module::Build 0.4 + Test::Compile 0 + Test::More 0 + Test::Pod 0 + perl v5.14.0 Travel-Status-DE-IRIS-1.72 pathname: D/DE/DERF/Travel-Status-DE-IRIS-1.72.tar.gz provides: @@ -1882,53 +1913,53 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 common::sense 0 - URI-5.12 - pathname: O/OA/OALDERS/URI-5.12.tar.gz - provides: - URI 5.12 - URI::Escape 5.12 - URI::Heuristic 5.12 - URI::IRI 5.12 - URI::QueryParam 5.12 - URI::Split 5.12 - URI::URL 5.12 - URI::WithBase 5.12 - URI::data 5.12 - URI::file 5.12 - URI::file::Base 5.12 - URI::file::FAT 5.12 - URI::file::Mac 5.12 - URI::file::OS2 5.12 - URI::file::QNX 5.12 - URI::file::Unix 5.12 - URI::file::Win32 5.12 - URI::ftp 5.12 - URI::gopher 5.12 - URI::http 5.12 - URI::https 5.12 - URI::ldap 5.12 - URI::ldapi 5.12 - URI::ldaps 5.12 - URI::mailto 5.12 - URI::mms 5.12 - URI::news 5.12 - URI::nntp 5.12 - URI::nntps 5.12 - URI::pop 5.12 - URI::rlogin 5.12 - URI::rsync 5.12 - URI::rtsp 5.12 - URI::rtspu 5.12 - URI::sftp 5.12 - URI::sip 5.12 - URI::sips 5.12 - URI::snews 5.12 - URI::ssh 5.12 - URI::telnet 5.12 - URI::tn3270 5.12 - URI::urn 5.12 - URI::urn::isbn 5.12 - URI::urn::oid 5.12 + URI-5.16 + pathname: O/OA/OALDERS/URI-5.16.tar.gz + provides: + URI 5.16 + URI::Escape 5.16 + URI::Heuristic 5.16 + URI::IRI 5.16 + URI::QueryParam 5.16 + URI::Split 5.16 + URI::URL 5.16 + URI::WithBase 5.16 + URI::data 5.16 + URI::file 5.16 + URI::file::Base 5.16 + URI::file::FAT 5.16 + URI::file::Mac 5.16 + URI::file::OS2 5.16 + URI::file::QNX 5.16 + URI::file::Unix 5.16 + URI::file::Win32 5.16 + URI::ftp 5.16 + URI::gopher 5.16 + URI::http 5.16 + URI::https 5.16 + URI::ldap 5.16 + URI::ldapi 5.16 + URI::ldaps 5.16 + URI::mailto 5.16 + URI::mms 5.16 + URI::news 5.16 + URI::nntp 5.16 + URI::nntps 5.16 + URI::pop 5.16 + URI::rlogin 5.16 + URI::rsync 5.16 + URI::rtsp 5.16 + URI::rtspu 5.16 + URI::sftp 5.16 + URI::sip 5.16 + URI::sips 5.16 + URI::snews 5.16 + URI::ssh 5.16 + URI::telnet 5.16 + URI::tn3270 5.16 + URI::urn 5.16 + URI::urn::isbn 5.16 + URI::urn::oid 5.16 requirements: Carp 0 Cwd 0 diff --git a/lib/DBInfoscreen.pm b/lib/DBInfoscreen.pm index 53944fd..23823f1 100644 --- a/lib/DBInfoscreen.pm +++ b/lib/DBInfoscreen.pm @@ -22,8 +22,6 @@ sub startup { my ($self) = @_; $self->config( - hafas_rest_api => $ENV{DBFAKEDISPLAY_HAFAS_API} - // 'https://v5.db.transport.rest', hypnotoad => { accepts => $ENV{DBFAKEDISPLAY_ACCEPTS} // 100, clients => $ENV{DBFAKEDISPLAY_CLIENTS} // 10, @@ -130,7 +128,6 @@ sub startup { hafas => sub { my ($self) = @_; state $hafas = DBInfoscreen::Helper::HAFAS->new( - api => $self->config->{hafas_rest_api}, log => $self->app->log, main_cache => $self->app->cache_iris_main, realtime_cache => $self->app->cache_iris_rt, diff --git a/lib/DBInfoscreen/Controller/Map.pm b/lib/DBInfoscreen/Controller/Map.pm index 4748e11..63b8b40 100644 --- a/lib/DBInfoscreen/Controller/Map.pm +++ b/lib/DBInfoscreen/Controller/Map.pm @@ -18,22 +18,27 @@ my $strp = DateTime::Format::Strptime->new( time_zone => 'Europe/Berlin', ); +# Input: +# - polyline: Travel::Status::DE::HAFAS::Journey->polyline +# - from_name: station name +# - to_name: station name +# Ouptut: +# - from_index: polyline index that corresponds to from_name +# - to_index: polyline index that corresponds to to_name sub get_route_indexes { - my ( $features, $from_name, $to_name ) = @_; + my ( $polyline, $from_name, $to_name ) = @_; my ( $from_index, $to_index ); - for my $i ( 0 .. $#{$features} ) { - my $this_point = $features->[$i]; + for my $i ( 0 .. $#{$polyline} ) { + my $this_point = $polyline->[$i]; if ( not defined $from_index - and $this_point->{properties}{type} - and $this_point->{properties}{type} eq 'stop' - and $this_point->{properties}{name} eq $from_name ) + and $this_point->{name} + and $this_point->{name} eq $from_name ) { $from_index = $i; } - elsif ( $this_point->{properties}{type} - and $this_point->{properties}{type} eq 'stop' - and $this_point->{properties}{name} eq $to_name ) + elsif ( $this_point->{name} + and $this_point->{name} eq $to_name ) { $to_index = $i; last; @@ -42,92 +47,14 @@ sub get_route_indexes { return ( $from_index, $to_index ); } -# Returns timestamped train positions between stop1 and stop2 (must not have -# intermittent stops) in 10-second steps. -sub estimate_timestamped_positions { - my (%opt) = @_; - - my $from_dt = $opt{from}{dep}; - my $to_dt = $opt{to}{arr}; - my $from_name = $opt{from}{name}; - my $to_name = $opt{to}{name}; - my $features = $opt{features}; - - my $duration = $to_dt->epoch - $from_dt->epoch; - - my @train_positions; - - my @completion_ratios - = map { ( $_ * 10 / $duration ) } ( 0 .. $duration / 10 ); - - my ( $from_index, $to_index ) - = get_route_indexes( $features, $from_name, $to_name ); - - my $location_epoch = $from_dt->epoch; - my $distance = GIS::Distance->new; - - if ( defined $from_index and defined $to_index ) { - my $total_distance = 0; - for my $j ( $from_index + 1 .. $to_index ) { - my $prev = $features->[ $j - 1 ]{geometry}{coordinates}; - my $this = $features->[$j]{geometry}{coordinates}; - if ( $prev and $this ) { - $total_distance - += $distance->distance_metal( $prev->[1], $prev->[0], - $this->[1], $this->[0] ); - } - } - my @marker_distances = map { $total_distance * $_ } @completion_ratios; - $total_distance = 0; - for my $j ( $from_index + 1 .. $to_index ) { - my $prev = $features->[ $j - 1 ]{geometry}{coordinates}; - my $this = $features->[$j]{geometry}{coordinates}; - if ( $prev and $this ) { - my $prev_distance = $total_distance; - $total_distance - += $distance->distance_metal( $prev->[1], $prev->[0], - $this->[1], $this->[0] ); - for my $i ( @train_positions .. $#marker_distances ) { - my $marker_distance = $marker_distances[$i]; - if ( $total_distance > $marker_distance ) { - - # completion ratio for the line between (prev, this) - my $sub_ratio = 1; - if ( $total_distance != $prev_distance ) { - $sub_ratio = ( $marker_distance - $prev_distance ) - / ( $total_distance - $prev_distance ); - } - - my $lat = $prev->[1] - + ( $this->[1] - $prev->[1] ) * $sub_ratio; - my $lon = $prev->[0] - + ( $this->[0] - $prev->[0] ) * $sub_ratio; - - push( @train_positions, - [ $location_epoch, $lat, $lon ] ); - $location_epoch += 10; - } - } - if ( @train_positions == @completion_ratios ) { - return @train_positions; - } - } - } - if (@train_positions) { - return @train_positions; - } - } - return; -} - # Input: # now: DateTime # from: current/previous stop # {dep => DateTime, name => str, lat => float, lon => float} # to: next stop # {arr => DateTime, name => str, lat => float, lon => float} -# features: https://github.com/public-transport/hafas-client/blob/5/docs/trip.md features array -# (with [lon, lat] coordinates in the geometry dict) +# route: Travel::Status::DE::HAFAS::Journey->route +# polyline: Travel::Status::DE::HAFAS::Journey->polyline (list of lon/lat hashes) # Output: list of estimated train positions in [lat, lon] format. # - current position # - position 2 seconds from now @@ -138,11 +65,12 @@ sub estimate_train_positions { my $now = $opt{now}; - my $from_dt = $opt{from}{dep} // $opt{from}{arr}; - my $to_dt = $opt{to}{arr} // $opt{to}{dep}; + my $from_dt = $opt{from}{dep} // $opt{from}{arr}; + my $to_dt = $opt{to}{arr} // $opt{to}{dep}; my $from_name = $opt{from}{name}; my $to_name = $opt{to}{name}; - my $features = $opt{features}; + my $route = $opt{route}; + my $polyline = $opt{polyline}; my @train_positions; @@ -155,29 +83,29 @@ sub estimate_train_positions { my $distance = GIS::Distance->new; my ( $from_index, $to_index ) - = get_route_indexes( $features, $from_name, $to_name ); + = get_route_indexes( $polyline, $from_name, $to_name ); if ( defined $from_index and defined $to_index ) { my $total_distance = 0; for my $j ( $from_index + 1 .. $to_index ) { - my $prev = $features->[ $j - 1 ]{geometry}{coordinates}; - my $this = $features->[$j]{geometry}{coordinates}; + my $prev = $polyline->[ $j - 1 ]; + my $this = $polyline->[$j]; if ( $prev and $this ) { $total_distance - += $distance->distance_metal( $prev->[1], $prev->[0], - $this->[1], $this->[0] ); + += $distance->distance_metal( $prev->{lat}, $prev->{lon}, + $this->{lat}, $this->{lon} ); } } my @marker_distances = map { $total_distance * $_ } @completion_ratios; $total_distance = 0; for my $j ( $from_index + 1 .. $to_index ) { - my $prev = $features->[ $j - 1 ]{geometry}{coordinates}; - my $this = $features->[$j]{geometry}{coordinates}; + my $prev = $polyline->[ $j - 1 ]; + my $this = $polyline->[$j]; if ( $prev and $this ) { my $prev_distance = $total_distance; $total_distance - += $distance->distance_metal( $prev->[1], $prev->[0], - $this->[1], $this->[0] ); + += $distance->distance_metal( $prev->{lat}, $prev->{lon}, + $this->{lat}, $this->{lon} ); for my $i ( @train_positions .. $#marker_distances ) { my $marker_distance = $marker_distances[$i]; if ( $total_distance > $marker_distance ) { @@ -189,10 +117,10 @@ sub estimate_train_positions { / ( $total_distance - $prev_distance ); } - my $lat = $prev->[1] - + ( $this->[1] - $prev->[1] ) * $sub_ratio; - my $lon = $prev->[0] - + ( $this->[0] - $prev->[0] ) * $sub_ratio; + my $lat = $prev->{lat} + + ( $this->{lat} - $prev->{lat} ) * $sub_ratio; + my $lon = $prev->{lon} + + ( $this->{lon} - $prev->{lon} ) * $sub_ratio; push( @train_positions, [ $lat, $lon ] ); } @@ -227,7 +155,7 @@ sub estimate_train_positions { # name: str # arr: DateTime # dep: DateTime -# features: ref to transport.rest features list +# polyline: ref to Travel::Status::DE::HAFAS::Journey polyline list # Output: # next_stop: {type, station} # positions: [current position [lat, lon], 2s from now, 4s from now, ...] @@ -258,7 +186,8 @@ sub estimate_train_positions2 { from => $route[ $i - 1 ], to => $route[$i], now => $now, - features => $opt{features}, + route => $opt{route}, + polyline => $opt{polyline}, ); $next_stop = { @@ -305,160 +234,18 @@ sub estimate_train_positions2 { }; } -sub estimate_train_intersection { - my (%opt) = @_; - my @route1 = @{ $opt{routes}[0] // [] }; - my @route2 = @{ $opt{routes}[1] // [] }; - - my $ret; - - my $i1 = 0; - my $i2 = 0; - - my @pairs; - my @meeting_points; - my $distance = GIS::Distance->new; - - # skip last route element as we compare route[i] with route[i+1] - while ( $i1 < $#route1 and $i2 < $#route2 ) { - my $dep1 = $route1[$i1]{dep}; - my $arr1 = $route1[ $i1 + 1 ]{arr}; - my $dep2 = $route2[$i2]{dep}; - my $arr2 = $route2[ $i2 + 1 ]{arr}; - - if ( not( $dep1 and $arr1 ) ) { - - #say "skip 1 $route1[$i1]{name}"; - $i1++; - next; - } - - if ( not( $dep2 and $arr2 ) ) { - - #say "skip 2 $route2[$i2]{name}"; - $i2++; - next; - } - - if ( $arr1 <= $dep2 ) { - $i1++; - } - elsif ( $arr2 <= $dep1 ) { - $i2++; - } - elsif ( $arr2 <= $arr1 ) { - push( @pairs, [ $i1, $i2 ] ); - if ( $route1[$i1]{name} eq $route2[ $i2 + 1 ]{name} - and $route2[$i2]{name} eq $route1[ $i1 + 1 ]{name} ) - { - # both i1 name == i2+1 name and i1 name == i2 name are valid cases - # (trains don't just intersect when they travel in opposing - # directions -- they may also travel in the same direction - # with different speed and overtake each other). - # We need both stop pairs later on, so we save both. - $ret->{stop_pair} = [ - [ $route1[$i1]{name}, $route1[ $i1 + 1 ]{name} ], - [ $route2[$i2]{name}, $route2[ $i2 + 1 ]{name} ] - ]; - } - $i2++; - } - elsif ( $arr1 <= $arr2 ) { - push( @pairs, [ $i1, $i2 ] ); - if ( $route1[$i1]{name} eq $route2[ $i2 + 1 ]{name} - and $route2[$i2]{name} eq $route1[ $i1 + 1 ]{name} ) - { - $ret->{stop_pair} = [ - [ $route1[$i1]{name}, $route1[ $i1 + 1 ]{name} ], - [ $route2[$i2]{name}, $route2[ $i2 + 1 ]{name} ] - ]; - } - $i1++; - } - else { - $i1++; - } - } - - for my $pair (@pairs) { - my ( $i1, $i2 ) = @{$pair}; - my @train1_positions = estimate_timestamped_positions( - from => $route1[$i1], - to => $route1[ $i1 + 1 ], - features => $opt{features}[0], - ); - my @train2_positions = estimate_timestamped_positions( - from => $route2[$i2], - to => $route2[ $i2 + 1 ], - features => $opt{features}[1], - ); - $i1 = 0; - $i2 = 0; - while ( $i1 <= $#train1_positions and $i2 <= $#train2_positions ) { - if ( $train1_positions[$i1][0] < $train2_positions[$i2][0] ) { - $i1++; - } - elsif ( $train1_positions[$i2][0] < $train2_positions[$i2][0] ) { - $i2++; - } - else { - if ( - ( - my $distance_km = $distance->distance_metal( - $train1_positions[$i1][1], - $train1_positions[$i1][2], - $train2_positions[$i2][1], - $train2_positions[$i2][2] - ) - ) < 1 - ) - { - my $ts = DateTime->from_epoch( - epoch => $train1_positions[$i1][0], - time_zone => 'Europe/Berlin' - ); - $ret->{first_meeting_time} //= $ts; - push( - @meeting_points, - { - timestamp => $ts, - lat => ( - $train1_positions[$i1][1] - + $train2_positions[$i2][1] - ) / 2, - lon => ( - $train1_positions[$i1][2] - + $train2_positions[$i2][2] - ) / 2, - distance => $distance_km, - } - ); - } - $i1++; - $i2++; - } - } - } - - $ret->{meeting_points} = \@meeting_points; - - return $ret; -} - sub route_to_ajax { my (@stopovers) = @_; my @route_entries; for my $stop (@stopovers) { - my @stop_entries = ( $stop->{stop}{name} ); + my @stop_entries = ( $stop->{name} ); my $platform; - if ( $stop->{arrival} - and my $arr = $strp->parse_datetime( $stop->{arrival} ) ) - { - my $delay = ( $stop->{arrivalDelay} // 0 ) / 60; - $platform = $stop->{arrivalPlatform}; + if ( my $arr = $stop->{arr} and not $stop->{arr_cancelled} ) { + my $delay = $stop->{arr_delay} // 0; + $platform = $stop->{arr_platform}; push( @stop_entries, $arr->epoch, $delay ); } @@ -466,11 +253,9 @@ sub route_to_ajax { push( @stop_entries, q{}, q{} ); } - if ( $stop->{departure} - and my $dep = $strp->parse_datetime( $stop->{departure} ) ) - { - my $delay = ( $stop->{departureDelay} // 0 ) / 60; - $platform //= $stop->{departurePlatform} // q{}; + if ( my $dep = $stop->{dep} and not $stop->{dep_cancelled} ) { + my $delay = $stop->{dep_delay} // 0; + $platform //= $stop->{dep_platform} // q{}; push( @stop_entries, $dep->epoch, $delay, $platform ); } @@ -484,56 +269,6 @@ sub route_to_ajax { return join( '|', @route_entries ); } -# Input: List of transport.rest stopovers -# Output: List of preprocessed stops. Each is a hash with the following keys: -# lat: float -# lon: float -# name: str -# arr: DateTime -# dep: DateTime -# arr_delay: int -# dep_delay: int -# platform: str -sub stopovers_to_route { - my (@stopovers) = @_; - my @route; - - for my $stop (@stopovers) { - my @stop_lines = ( $stop->{stop}{name} ); - my ( $platform, $arr, $dep, $arr_delay, $dep_delay ); - - if ( $stop->{arrival} - and $arr = $strp->parse_datetime( $stop->{arrival} ) ) - { - $arr_delay = ( $stop->{arrivalDelay} // 0 ) / 60; - $platform //= $stop->{arrivalPlatform}; - } - - if ( $stop->{departure} - and $dep = $strp->parse_datetime( $stop->{departure} ) ) - { - $dep_delay = ( $stop->{departureDelay} // 0 ) / 60; - $platform //= $stop->{departurePlatform}; - } - - push( - @route, - { - lat => $stop->{stop}{location}{latitude}, - lon => $stop->{stop}{location}{longitude}, - name => $stop->{stop}{name}, - arr => $arr, - dep => $dep, - arr_delay => $arr_delay, - dep_delay => $dep_delay, - platform => $platform, - } - ); - - } - return @route; -} - sub polyline_to_line_pairs { my (@polyline) = @_; my @line_pairs; @@ -541,138 +276,14 @@ sub polyline_to_line_pairs { push( @line_pairs, [ - [ $polyline[ $i - 1 ][1], $polyline[ $i - 1 ][0] ], - [ $polyline[$i][1], $polyline[$i][0] ] + [ $polyline[ $i - 1 ]{lat}, $polyline[ $i - 1 ]{lon} ], + [ $polyline[$i]{lat}, $polyline[$i]{lon} ] ] ); } return @line_pairs; } -sub intersection { - my ($self) = @_; - - my @trips = split( qr{;}, $self->stash('trips') ); - my @trip_ids = map { [ split( qr{,}, $_ ) ] } @trips; - - $self->render_later; - - my @polyline_requests - = map { $self->hafas->get_polyline_p( @{$_} ) } @trip_ids; - Mojo::Promise->all(@polyline_requests)->then( - sub { - my ( $pl1, $pl2 ) = map { $_->[0] } @_; - my @polyline1 = @{ $pl1->{polyline} }; - my @polyline2 = @{ $pl2->{polyline} }; - my @station_coordinates; - - my @markers; - my $next_stop; - - my $now = DateTime->now( time_zone => 'Europe/Berlin' ); - - my @line1_pairs = polyline_to_line_pairs(@polyline1); - my @line2_pairs = polyline_to_line_pairs(@polyline2); - - my @route1 - = stopovers_to_route( @{ $pl1->{raw}{stopovers} // [] } ); - my @route2 - = stopovers_to_route( @{ $pl2->{raw}{stopovers} // [] } ); - - my $train1_pos = $self->estimate_train_positions2( - now => $now, - route => \@route1, - features => $pl1->{raw}{polyline}{features}, - ); - - my $train2_pos = $self->estimate_train_positions2( - now => $now, - route => \@route2, - features => $pl2->{raw}{polyline}{features}, - ); - - my $intersection = estimate_train_intersection( - routes => [ \@route1, \@route2 ], - features => [ - $pl1->{raw}{polyline}{features}, - $pl2->{raw}{polyline}{features} - ], - ); - - for my $meeting_point ( @{ $intersection->{meeting_points} } ) { - push( - @station_coordinates, - [ - [ $meeting_point->{lat}, $meeting_point->{lon} ], - [ $meeting_point->{timestamp}->strftime('%H:%M') ] - ] - ); - } - - push( - @markers, - { - lat => $train1_pos->{position_now}[0], - lon => $train1_pos->{position_now}[1], - title => $pl1->{name} - }, - { - lat => $train2_pos->{position_now}[0], - lon => $train2_pos->{position_now}[1], - title => $pl2->{name} - }, - ); - - $self->render( - 'route_map', - title => "DBF", - hide_opts => 1, - with_map => 1, - intersection => 1, - train1_no => - scalar( $pl1->{raw}{line}{additionalName} // $pl1->{name} ), - train2_no => - scalar( $pl2->{raw}{line}{additionalName} // $pl2->{name} ), - likely_pair => $intersection->{stop_pair} - ? $intersection->{stop_pair}[0] - : undef, - time => scalar $intersection->{first_meeting_time}, - polyline_groups => [ - { - polylines => [ @line1_pairs, @line2_pairs ], - color => '#ffffff', - opacity => 0, - fit_bounds => 1, - }, - { - polylines => [@line1_pairs], - color => '#005080', - opacity => 0.6, - }, - { - polylines => [@line2_pairs], - color => '#800050', - opacity => 0.6, - } - ], - markers => [@markers], - station_coordinates => [@station_coordinates], - ); - } - )->catch( - sub { - my ($err) = @_; - $self->render( - 'route_map', - title => "DBF", - hide_opts => 1, - with_map => 1, - error => $err, - ); - } - )->wait; -} - sub backpropagate_delay { my ( $self, $prev_stop, $next_stop ) = @_; @@ -704,9 +315,9 @@ sub route { $self->hafas->get_polyline_p( $trip_id, $line_no )->then( sub { - my ($pl) = @_; + my ($journey) = @_; - my @polyline = @{ $pl->{polyline} }; + my @polyline = $journey->polyline; my @station_coordinates; my @markers; @@ -717,12 +328,12 @@ sub route { # used to draw the train's journey on the map my @line_pairs = polyline_to_line_pairs(@polyline); - my @route = stopovers_to_route( @{ $pl->{raw}{stopovers} // [] } ); + my @route = $journey->route; my $train_pos = $self->estimate_train_positions2( now => $now, route => \@route, - features => $pl->{raw}{polyline}{features}, + polyline => \@polyline, ); # Prepare from/to markers and name/time/delay overlays for stations @@ -779,34 +390,32 @@ sub route { { lat => $train_pos->{position_now}[0], lon => $train_pos->{position_now}[1], - title => $pl->{name} + title => $journey->name } ); $next_stop = $train_pos->{next_stop}; $self->render( 'route_map', - title => $pl->{name}, - hide_opts => 1, - with_map => 1, - ajax_req => "${trip_id}/${line_no}", - ajax_route => route_to_ajax( @{ $pl->{raw}{stopovers} // [] } ), + title => $journey->name, + hide_opts => 1, + with_map => 1, + ajax_req => "${trip_id}/${line_no}", + ajax_route => route_to_ajax( $journey->route ), ajax_polyline => join( '|', map { join( ';', @{$_} ) } @{ $train_pos->{positions} } ), origin => { - name => $pl->{raw}{origin}{name}, - ts => $pl->{raw}{departure} - ? scalar $strp->parse_datetime( $pl->{raw}{departure} ) - : undef, + name => $journey->route_start, + ts => ( $journey->route )[0]->{dep}, }, destination => { - name => $pl->{raw}{destination}{name}, - ts => $pl->{raw}{arrival} - ? scalar $strp->parse_datetime( $pl->{raw}{arrival} ) - : undef, + name => $journey->route_end, + ts => ( $journey->route )[-1]->{arr}, }, - train_no => scalar $pl->{raw}{line}{additionalName}, - operator => scalar $pl->{raw}{line}{operator}{name}, + train_no => $journey->number + ? ( $journey->type . ' ' . $journey->number ) + : undef, + operator => $journey->operator, next_stop => $next_stop, polyline_groups => [ { @@ -817,7 +426,7 @@ sub route { } ], station_coordinates => [@station_coordinates], - station_radius => + station_radius => ( $train_pos->{avg_inter_stop_beeline} > 500 ? 250 : 100 ), markers => [@markers], ); @@ -848,36 +457,32 @@ sub ajax_route { $self->hafas->get_polyline_p( $trip_id, $line_no )->then( sub { - my ($pl) = @_; + my ($journey) = @_; my $now = DateTime->now( time_zone => 'Europe/Berlin' ); - my @route = stopovers_to_route( @{ $pl->{raw}{stopovers} // [] } ); + my @route = $journey->route; + my @polyline = $journey->polyline; my $train_pos = $self->estimate_train_positions2( now => $now, route => \@route, - features => $pl->{raw}{polyline}{features}, + polyline => \@polyline, ); - my @polyline = @{ $pl->{polyline} }; $self->render( '_map_infobox', - ajax_req => "${trip_id}/${line_no}", - ajax_route => route_to_ajax( @{ $pl->{raw}{stopovers} // [] } ), + ajax_req => "${trip_id}/${line_no}", + ajax_route => route_to_ajax(@route), ajax_polyline => join( '|', map { join( ';', @{$_} ) } @{ $train_pos->{positions} } ), origin => { - name => $pl->{raw}{origin}{name}, - ts => $pl->{raw}{departure} - ? scalar $strp->parse_datetime( $pl->{raw}{departure} ) - : undef, + name => $journey->route_start, + ts => ( $journey->route )[0]->{dep}, }, destination => { - name => $pl->{raw}{destination}{name}, - ts => $pl->{raw}{arrival} - ? scalar $strp->parse_datetime( $pl->{raw}{arrival} ) - : undef, + name => $journey->route_end, + ts => ( $journey->route )[-1]->{arr}, }, next_stop => $train_pos->{next_stop}, ); diff --git a/lib/DBInfoscreen/Helper/HAFAS.pm b/lib/DBInfoscreen/Helper/HAFAS.pm index 48632c0..a13fd4a 100644 --- a/lib/DBInfoscreen/Helper/HAFAS.pm +++ b/lib/DBInfoscreen/Helper/HAFAS.pm @@ -10,6 +10,7 @@ use 5.020; use DateTime; use Encode qw(decode encode); +use Travel::Status::DE::HAFAS; use Mojo::JSON qw(decode_json); use Mojo::Promise; use XML::LibXML; @@ -438,68 +439,33 @@ sub get_route_timestamps_p { } # Input: (HAFAS TripID, line number) -# Output: Promise returning a -# https://github.com/public-transport/hafas-client/blob/4/docs/trip.md instance -# on success +# Output: Promise returning a Travel::Status::DE::HAFAS::Journey instance on success sub get_polyline_p { my ( $self, $trip_id, $line ) = @_; - my $api = $self->{api}; - my $url = "${api}/trips/${trip_id}?lineName=${line}&polyline=true"; - my $log_url = $url; - my $cache = $self->{realtime_cache}; my $promise = Mojo::Promise->new; - $log_url =~ s{://\K[^:]+:[^@]+\@}{***@}; - - if ( my $content = $cache->thaw($url) ) { - $promise->resolve($content); - $self->{log}->debug("GET $log_url (cached)"); - return $promise; - } - - $self->{user_agent}->request_timeout(5)->get_p( $url => $self->{header} ) - ->then( + Travel::Status::DE::HAFAS->new_p( + journey => { + id => $trip_id, + name => $line, + }, + with_polyline => 1, + cache => $self->{realtime_cache}, + promise => 'Mojo::Promise', + user_agent => $self->{user_agent}->request_timeout(5) + )->then( sub { - my ($tx) = @_; + my ($hafas) = @_; + my $journey = $hafas->result; - if ( my $err = $tx->error ) { - $self->{log}->warn( -"hafas->get_polyline_p($log_url): HTTP $err->{code} $err->{message}" - ); - $promise->reject( - "GET $log_url returned HTTP $err->{code} $err->{message}"); - return; - } - - $self->{log}->debug("GET $log_url (OK)"); - my $json = decode_json( $tx->res->body ); - my @coordinate_list; - - for my $feature ( @{ $json->{polyline}{features} } ) { - if ( exists $feature->{geometry}{coordinates} ) { - push( @coordinate_list, $feature->{geometry}{coordinates} ); - } - - #if ($feature->{type} eq 'Feature') { - # say "Feature " . $feature->{properties}{name}; - #} - } - - my $ret = { - name => $json->{line}{name} // '?', - polyline => [@coordinate_list], - raw => $json, - }; - - $cache->freeze( $url, $ret ); - $promise->resolve($ret); + $promise->resolve($journey); return; } )->catch( sub { my ($err) = @_; - $self->{log}->debug("GET $log_url (error: $err)"); + $self->{log}->debug("HAFAS->new_p($trip_id, $line) error: $err"); $promise->reject($err); return; } diff --git a/templates/about.html.ep b/templates/about.html.ep index df5d3e6..1c04456 100644 --- a/templates/about.html.ep +++ b/templates/about.html.ep @@ -31,12 +31,11 @@ v<%= $Travel::Status::DE::DBWagenreihung::VERSION %> % }
- % if (app->config->{hafas_rest_api} =~ m{v5.db.transport.rest}) { - • Karte: DB HAFAS via v5.db.transport.rest
- % } - % else { - • Karte: DB HAFAS via hafas-rest-api
+ • Karte: Travel::Status::DE::HAFAS + % if ($Travel::Status::DE::HAFAS::VERSION) { + v<%= $Travel::Status::DE::HAFAS::VERSION %> % } +
• Zugauslastung Fernverkehr: DB HAFAS via bahn.expert
• Zugauslastung Regionalverkehr: VRR EFA via eva-to-efa-gw

-- cgit v1.2.3