diff options
| -rw-r--r-- | cpanfile | 1 | ||||
| -rw-r--r-- | cpanfile.snapshot | 1099 | ||||
| -rw-r--r-- | lib/DBInfoscreen.pm | 3 | ||||
| -rw-r--r-- | lib/DBInfoscreen/Controller/Map.pm | 543 | ||||
| -rw-r--r-- | lib/DBInfoscreen/Helper/HAFAS.pm | 66 | ||||
| -rw-r--r-- | templates/about.html.ep | 9 | 
6 files changed, 660 insertions, 1061 deletions
| @@ -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 %>  		% }  		<br/> -		% if (app->config->{hafas_rest_api} =~ m{v5.db.transport.rest}) { -			• Karte: DB HAFAS via <a href="https://v5.db.transport.rest/">v5.db.transport.rest</a><br/> -		% } -		% else { -			• Karte: DB HAFAS via <a href="https://github.com/public-transport/hafas-rest-api">hafas-rest-api</a><br/> +		• Karte: <a href="https://finalrewind.org/projects/Travel-Status-DE-DeutscheBahn/">Travel::Status::DE::HAFAS</a> +		% if ($Travel::Status::DE::HAFAS::VERSION) { +			v<%= $Travel::Status::DE::HAFAS::VERSION %>  		% } +		<br/>  		• Zugauslastung Fernverkehr: DB HAFAS via <a href="https://docs.bahn.expert/">bahn.expert</a><br/>  		• Zugauslastung Regionalverkehr: VRR EFA via <a href="https://github.com/derf/eva-to-efa-gw">eva-to-efa-gw</a><br/>  		<br/> | 
