<?php
/*
Программа: поиск пути
Версия:5.0
На данном этапе программа:
-ищет самый короткий путь из точки A в B
-показывает время достижения пути
-показывает способ достижения пути
-показывает, на чём добираться
-сколько времени это займёт
Todo:
-возможно, сделать для метро
-изменить структуру кода (что-бы путь Медведково=>Проспект Мира не показывал все промежуточные станции)
-долго вбивать все станции (взять в Яндексе или найти где-нибудь еще)
-можно сделать 2-3 ветки и не париться
-сделать web-интерфейс с приложенной картой (http://content-available-to-author-only.cc/55nguY) и формой
-немного современного дизайна
*/
SUBWAY => 'на метро' ,
FOOT => 'пешком' ,
BUS => 'на автобусе'
) ;
'pet' => 'ст. м. Петроградская' ,
'chk' => 'ст. м. Чкаловская' ,
'gor' => 'ст. м. Горьковская' ,
'spo' => 'ст. м. Спортивная' ,
'vas' => 'ст. м. Василеостровская' ,
'kre' => 'Петропавловская крепость' ,
'let' => 'Летний сад' ,
'dvo' => 'Дворцовая площадь' ,
'isa' => 'Исакиевский собор' ,
'nov' => 'Новая Голландия' ,
'ras' => 'Дом Раскольникова' ,
'gos' => 'Гостиный Двор' ,
'sen' => 'Сенная Площадь' ,
'vla' => 'ст. м. Владимирская' ,
'vit' => 'Витебский вокзал' ,
'teh' => 'Технологический Институт'
) ;
'chk' => canGet( 10 , BUS) ,
'gor' => canGet( 3 , SUBWAY)
) ,
'pet' => canGet( 10 , BUS) ,
'spo' => canGet( 3 , SUBWAY)
) ,
'pet' => canGet( 3 , BUS) ,
'kre' => canGet( 5 , FOOT) ,
'gos' => canGet( 6 , SUBWAY)
) ,
'chk' => canGet( 3 , SUBWAY) ,
'vas' => canGet( 10 , BUS) ,
'sen' => canGet( 7 , SUBWAY)
) ,
'spo' => canGet( 10 , BUS) ,
'gos' => canGet( 7 , SUBWAY) ,
'nov' => canGet( 11 , FOOT)
) ,
'gor' => canGet( 5 , FOOT)
) ,
'dvo' => canGet( 6 , FOOT) ,
'gos' => canGet( 7 , FOOT)
) ,
'isa' => canGet( 6 , FOOT) ,
'gos' => canGet( 6 , FOOT) ,
'let' => canGet( 6 , FOOT)
) ,
'dvo' => canGet( 6 , FOOT) ,
'nov' => canGet( 5 , FOOT)
) ,
'vas' => canGet( 11 , FOOT) ,
'isa' => canGet( 5 , FOOT) ,
'ras' => canGet( 7 , BUS)
) ,
'nov' => canGet( 7 , BUS) ,
'sen' => canGet( 3 , FOOT)
) ,
'vas' => canGet( 7 , SUBWAY) ,
'sen' => canGet( 3 , SUBWAY) ,
'dvo' => canGet( 6 , FOOT) ,
'gor' => canGet( 6 , SUBWAY) ,
'let' => canGet( 7 , FOOT) ,
'vla' => canGet( 7 , FOOT)
) ,
'ras' => canGet( 3 , FOOT) ,
'spo' => canGet( 7 , SUBWAY) ,
'gos' => canGet( 3 , SUBWAY) ,
'vla' => canGet( 4 , SUBWAY) ,
'vit' => canGet( 2 , SUBWAY) ,
'teh' => canGet( 3 , SUBWAY)
) ,
'sen' => canGet( 4 , SUBWAY) ,
'gos' => canGet( 7 , FOOT) ,
'vit' => canGet( 3 , SUBWAY)
) ,
'sen' => canGet( 2 , SUBWAY) ,
'teh' => canGet( 2 , SUBWAY) ,
'vla' => canGet( 3 , SUBWAY)
) ,
'sen' => canGet( 3 , SUBWAY) ,
'vit' => canGet( 2 , SUBWAY)
)
) ;
/* Чтобы не писать много раз array('time' => ..., 'by' => ...), используем функцию.
«canGet» переводится как «можно попасть» */
function canGet( $time , $byWhat ) {
return array ( 'time' => $time , 'by' => $byWhat ) ; }
function find_way( $paths , $from , $where , $time , $way ) {
$way [ ] = $from ;
}
$current = $way [ count ( $way ) - 1 ] ; //на какой мы сейчас станции
//Считаем время
$prev = $way [ count ( $way ) - 2 ] ; //Предыдущая станция(для времени) $time += $paths [ $prev ] [ $current ] [ 'time' ] ;
}
$way [ ] = $where ;
$time += $paths [ $current ] [ $where ] [ 'time' ] ; //Время текущей с следующей (,которая цель)
$arrPrep [ 'way' ] = $way ;
$arrPrep [ 'time' ] = $time ;
$GLOBALS [ 'ways' ] [ ] = $arrPrep ; //Добавляем вариант прохода в возвращаемый функцией массив
}
else {
foreach ( $paths [ $current ] as $k => $v ) {
$next = $k ;
$way [ ] = $next ;
find_way( $paths , $from , $where , $time , $way ) ;
}
}
}
if ( isset ( $GLOBALS [ 'ways' ] ) ) return ( $GLOBALS [ 'ways' ] ) ;
}
////////////////////////////////////
function find_shortest_way( $paths , $from , $where , $time , $way ) {
$ways = find_way( $paths , $from , $where , $time , $way ) ;
$shortest [ 'time' ] = 0 ;
$shortest [ 'way' ] = '' ;
foreach ( $ways as $k => $v ) {
if ( ( $shortest [ 'time' ] > $ways [ $k ] [ 'time' ] ) || ( $shortest [ 'time' ] == 0 ) ) {
$shortest [ 'time' ] = $ways [ $k ] [ 'time' ] ;
$shortest [ 'way' ] = $ways [ $k ] [ 'way' ] ;
}
}
return $shortest ;
}
////////////////////////////////////
function show_shortest_way( $paths , $from , $where , $time , $way , $pointNames , $transportName ) {
$ways = find_shortest_way( $paths , $from , $where , $time , $way ) ;
$first = $pointNames [ reset ( $ways [ 'way' ] ) ] ; $last = $pointNames [ end ( $ways [ 'way' ] ) ] ;
echo "Как доехать из " . $first . " в " . $last . " за " . $ways [ 'time' ] . " минут\n " ;
for ( $i = 0 ; $i < count ( $ways [ 'way' ] ) ; $i ++ ) { $current = $ways [ 'way' ] [ $i ] ;
if ( $i < ( count ( $ways [ 'way' ] ) - 1 ) ) { $next = $ways [ 'way' ] [ $i + 1 ] ;
echo "" . $pointNames [ $current ] . "\n =>" ;
echo $transportName [ $paths [ $current ] [ $next ] [ 'by' ] ] . "" ;
echo " за " . $paths [ $current ] [ $next ] [ 'time' ] . " минут\n " ;
}
else
echo $pointNames [ $current ] . "\n \n " ;
}
}
////////////////////////////////////
show_shortest_way( $paths , 'pet' , 'teh' , 0 , null , $pointNames , $transportName ) ;
show_shortest_way( $paths , 'vas' , 'let' , 0 , null , $pointNames , $transportName ) ;
PD9waHAKCi8qCtCf0YDQvtCz0YDQsNC80LzQsDog0L/QvtC40YHQuiDQv9GD0YLQuArQktC10YDRgdC40Y86NS4wCtCd0LAg0LTQsNC90L3QvtC8INGN0YLQsNC/0LUg0L/RgNC+0LPRgNCw0LzQvNCwOgoJLdC40YnQtdGCINGB0LDQvNGL0Lkg0LrQvtGA0L7RgtC60LjQuSDQv9GD0YLRjCDQuNC3INGC0L7Rh9C60LggQSDQsiBCCgkt0L/QvtC60LDQt9GL0LLQsNC10YIg0LLRgNC10LzRjyDQtNC+0YHRgtC40LbQtdC90LjRjyDQv9GD0YLQuAoJLdC/0L7QutCw0LfRi9Cy0LDQtdGCINGB0L/QvtGB0L7QsSDQtNC+0YHRgtC40LbQtdC90LjRjyDQv9GD0YLQuAoJCS3Qv9C+0LrQsNC30YvQstCw0LXRgiwg0L3QsCDRh9GR0Lwg0LTQvtCx0LjRgNCw0YLRjNGB0Y8KCQkt0YHQutC+0LvRjNC60L4g0LLRgNC10LzQtdC90Lgg0Y3RgtC+INC30LDQudC80ZHRggoJCQoJCQpUb2RvOgot0LLQvtC30LzQvtC20L3Qviwg0YHQtNC10LvQsNGC0Ywg0LTQu9GPINC80LXRgtGA0L4KCS3QuNC30LzQtdC90LjRgtGMINGB0YLRgNGD0LrRgtGD0YDRgyDQutC+0LTQsCAo0YfRgtC+LdCx0Ysg0L/Rg9GC0Ywg0JzQtdC00LLQtdC00LrQvtCy0L49PtCf0YDQvtGB0L/QtdC60YIg0JzQuNGA0LAg0L3QtSDQv9C+0LrQsNC30YvQstCw0Lsg0LLRgdC1INC/0YDQvtC80LXQttGD0YLQvtGH0L3Ri9C1INGB0YLQsNC90YbQuNC4KQoJLdC00L7Qu9Cz0L4g0LLQsdC40LLQsNGC0Ywg0LLRgdC1INGB0YLQsNC90YbQuNC4ICjQstC30Y/RgtGMINCyINCv0L3QtNC10LrRgdC1INC40LvQuCDQvdCw0LnRgtC4INCz0LTQtS3QvdC40LHRg9C00Ywg0LXRidC1KQoJLdC80L7QttC90L4g0YHQtNC10LvQsNGC0YwgMi0zINCy0LXRgtC60Lgg0Lgg0L3QtSDQv9Cw0YDQuNGC0YzRgdGPCgkKLdGB0LTQtdC70LDRgtGMIHdlYi3QuNC90YLQtdGA0YTQtdC50YEg0YEg0L/RgNC40LvQvtC20LXQvdC90L7QuSDQutCw0YDRgtC+0LkgKGh0dHA6Ly9jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS5jYy81NW5ndVkpINC4INGE0L7RgNC80L7QuQot0L3QtdC80L3QvtCz0L4g0YHQvtCy0YDQtdC80LXQvdC90L7Qs9C+INC00LjQt9Cw0LnQvdCwCgkKKi8KZXJyb3JfcmVwb3J0aW5nKC0xKTsKCmRlZmluZSgnU1VCV0FZJywgJ3N1YicpOwpkZWZpbmUoJ0ZPT1QnLCAnZm9vdCcpOwpkZWZpbmUoJ0JVUycsICdidXMnKTsKCiR0cmFuc3BvcnROYW1lID0gYXJyYXkoCiAgICBTVUJXQVkgID0+ICAn0L3QsCDQvNC10YLRgNC+JywKICAgIEZPT1QgICAgPT4gICfQv9C10YjQutC+0LwnLAogICAgQlVTICAgICA9PiAgJ9C90LAg0LDQstGC0L7QsdGD0YHQtScKKTsKCiRwb2ludE5hbWVzID0gYXJyYXkoCiAgICAncGV0JyAgID0+ICAn0YHRgi4g0LwuINCf0LXRgtGA0L7Qs9GA0LDQtNGB0LrQsNGPJywKICAgICdjaGsnICAgPT4gICfRgdGCLiDQvC4g0KfQutCw0LvQvtCy0YHQutCw0Y8nLAogICAgJ2dvcicgICA9PiAgJ9GB0YIuINC8LiDQk9C+0YDRjNC60L7QstGB0LrQsNGPJywKICAgICdzcG8nICAgPT4gICfRgdGCLiDQvC4g0KHQv9C+0YDRgtC40LLQvdCw0Y8nLAogICAgJ3ZhcycgICA9PiAgJ9GB0YIuINC8LiDQktCw0YHQuNC70LXQvtGB0YLRgNC+0LLRgdC60LDRjycsCiAgICAna3JlJyAgID0+ICAn0J/QtdGC0YDQvtC/0LDQstC70L7QstGB0LrQsNGPINC60YDQtdC/0L7RgdGC0YwnLAogICAgJ2xldCcgICA9PiAgJ9Cb0LXRgtC90LjQuSDRgdCw0LQnLAogICAgJ2R2bycgICA9PiAgJ9CU0LLQvtGA0YbQvtCy0LDRjyDQv9C70L7RidCw0LTRjCcsCiAgICAnaXNhJyAgID0+ICAn0JjRgdCw0LrQuNC10LLRgdC60LjQuSDRgdC+0LHQvtGAJywKICAgICdub3YnICAgPT4gICfQndC+0LLQsNGPINCT0L7Qu9C70LDQvdC00LjRjycsCiAgICAncmFzJyAgID0+ICAn0JTQvtC8INCg0LDRgdC60L7Qu9GM0L3QuNC60L7QstCwJywKICAgICdnb3MnICAgPT4gICfQk9C+0YHRgtC40L3Ri9C5INCU0LLQvtGAJywKICAgICdzZW4nICAgPT4gICfQodC10L3QvdCw0Y8g0J/Qu9C+0YnQsNC00YwnLAogICAgJ3ZsYScgICA9PiAgJ9GB0YIuINC8LiDQktC70LDQtNC40LzQuNGA0YHQutCw0Y8nLAogICAgJ3ZpdCcgICA9PiAgJ9CS0LjRgtC10LHRgdC60LjQuSDQstC+0LrQt9Cw0LsnLAogICAgJ3RlaCcgICA9PiAgJ9Ci0LXRhdC90L7Qu9C+0LPQuNGH0LXRgdC60LjQuSDQmNC90YHRgtC40YLRg9GCJwopOwoKJHBhdGhzID0gYXJyYXkoCiAgICAncGV0JyAgID0+ICBhcnJheSgKICAgICAgICAnY2hrJyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgJ2dvcicgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCgogICAgJ2NoaycgICA9PiAgYXJyYXkoCiAgICAgICAgJ3BldCcgICA9PiAgY2FuR2V0KDEwLCBCVVMpLAogICAgICAgICdzcG8nICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAoKICAgICdnb3InICAgPT4gIGFycmF5KAogICAgICAgICdwZXQnICAgPT4gIGNhbkdldCgzLCBCVVMpLAogICAgICAgICdrcmUnICAgPT4gIGNhbkdldCg1LCBGT09UKSwKICAgICAgICAnZ29zJyAgID0+ICBjYW5HZXQoNiwgU1VCV0FZKQogICAgKSwKCiAgICAnc3BvJyAgID0+ICBhcnJheSgKICAgICAgICAnY2hrJyAgID0+ICBjYW5HZXQoMywgU1VCV0FZKSwKICAgICAgICAndmFzJyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgJ3NlbicgICA9PiAgY2FuR2V0KDcsIFNVQldBWSkKICAgICksCgogICAgJ3ZhcycgICA9PiAgYXJyYXkoCiAgICAgICAgJ3NwbycgICA9PiAgY2FuR2V0KDEwLCBCVVMpLAogICAgICAgICdnb3MnICAgPT4gIGNhbkdldCg3LCBTVUJXQVkpLAogICAgICAgICdub3YnICAgPT4gIGNhbkdldCgxMSwgRk9PVCkKICAgICksCgogICAgJ2tyZScgICA9PiAgYXJyYXkoCiAgICAgICAgJ2dvcicgICA9PiAgY2FuR2V0KDUsIEZPT1QpCiAgICApLAoKICAgICdsZXQnICAgPT4gIGFycmF5KAogICAgICAgICdkdm8nICAgPT4gIGNhbkdldCg2LCBGT09UKSwKICAgICAgICAnZ29zJyAgID0+ICBjYW5HZXQoNywgRk9PVCkKICAgICksCgogICAgJ2R2bycgICA9PiAgYXJyYXkoCiAgICAgICAgJ2lzYScgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdnb3MnICAgPT4gIGNhbkdldCg2LCBGT09UKSwKICAgICAgICAnbGV0JyAgID0+ICBjYW5HZXQoNiwgRk9PVCkKICAgICksCgogICAgJ2lzYScgICA9PiAgYXJyYXkoCiAgICAgICAgJ2R2bycgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdub3YnICAgPT4gIGNhbkdldCg1LCBGT09UKQogICAgKSwKCiAgICAnbm92JyAgID0+ICBhcnJheSgKICAgICAgICAndmFzJyAgID0+ICBjYW5HZXQoMTEsIEZPT1QpLAogICAgICAgICdpc2EnICAgPT4gIGNhbkdldCg1LCBGT09UKSwKICAgICAgICAncmFzJyAgID0+ICBjYW5HZXQoNywgQlVTKQogICAgKSwKCiAgICAncmFzJyAgID0+ICBhcnJheSgKICAgICAgICAnbm92JyAgID0+ICBjYW5HZXQoNywgQlVTKSwKICAgICAgICAnc2VuJyAgID0+ICBjYW5HZXQoMywgRk9PVCkKICAgICksCgogICAgJ2dvcycgICA9PiAgYXJyYXkoCiAgICAgICAgJ3ZhcycgICA9PiAgY2FuR2V0KDcsIFNVQldBWSksCiAgICAgICAgJ3NlbicgICA9PiAgY2FuR2V0KDMsIFNVQldBWSksCiAgICAgICAgJ2R2bycgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdnb3InICAgPT4gIGNhbkdldCg2LCBTVUJXQVkpLAogICAgICAgICdsZXQnICAgPT4gIGNhbkdldCg3LCBGT09UKSwKICAgICAgICAndmxhJyAgID0+ICBjYW5HZXQoNywgRk9PVCkgICAgICAgIAogICAgKSwKCiAgICAnc2VuJyAgID0+ICBhcnJheSgKICAgICAgICAncmFzJyAgID0+ICBjYW5HZXQoMywgRk9PVCksCiAgICAgICAgJ3NwbycgICA9PiAgY2FuR2V0KDcsIFNVQldBWSksCiAgICAgICAgJ2dvcycgICA9PiAgY2FuR2V0KDMsIFNVQldBWSksCiAgICAgICAgJ3ZsYScgICA9PiAgY2FuR2V0KDQsIFNVQldBWSksCiAgICAgICAgJ3ZpdCcgICA9PiAgY2FuR2V0KDIsIFNVQldBWSksCiAgICAgICAgJ3RlaCcgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCgogICAgJ3ZsYScgICA9PiAgYXJyYXkoCiAgICAgICAgJ3NlbicgICA9PiAgY2FuR2V0KDQsIFNVQldBWSksCiAgICAgICAgJ2dvcycgICA9PiAgY2FuR2V0KDcsIEZPT1QpLAogICAgICAgICd2aXQnICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAoKICAgICd2aXQnICAgPT4gIGFycmF5KAogICAgICAgICdzZW4nICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpLAogICAgICAgICd0ZWgnICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpLAogICAgICAgICd2bGEnICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAoKICAgICd0ZWgnICAgPT4gIGFycmF5KAogICAgICAgICdzZW4nICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpLAogICAgICAgICd2aXQnICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpICAgICAgICAKICAgICkKKTsKCi8qINCn0YLQvtCx0Ysg0L3QtSDQv9C40YHQsNGC0Ywg0LzQvdC+0LPQviDRgNCw0LcgYXJyYXkoJ3RpbWUnID0+IC4uLiwgJ2J5JyA9PiAuLi4pLCDQuNGB0L/QvtC70YzQt9GD0LXQvCDRhNGD0L3QutGG0LjRji4gCiAgICDCq2NhbkdldMK7INC/0LXRgNC10LLQvtC00LjRgtGB0Y8g0LrQsNC6IMKr0LzQvtC20L3QviDQv9C+0L/QsNGB0YLRjMK7ICovCmZ1bmN0aW9uIGNhbkdldCgkdGltZSwgJGJ5V2hhdCkgewogICAgcmV0dXJuIGFycmF5KCd0aW1lJyAgICAgPT4gICR0aW1lLCAnYnknID0+ICAkYnlXaGF0KTsKfQoKZnVuY3Rpb24gZmluZF93YXkoJHBhdGhzLCRmcm9tLCR3aGVyZSwkdGltZSwkd2F5KXsKCglpZiAoIWlzX2FycmF5KCR3YXkpKXsKCQkkd2F5PWFycmF5KCk7CgkJJHdheVtdPSRmcm9tOwoJfQoKCSRjdXJyZW50PSR3YXlbY291bnQoJHdheSktMV07IC8v0L3QsCDQutCw0LrQvtC5INC80Ysg0YHQtdC50YfQsNGBINGB0YLQsNC90YbQuNC4CgkKCS8v0KHRh9C40YLQsNC10Lwg0LLRgNC10LzRjwoJaWYgKGNvdW50KCR3YXkpPjEpewoJCSRwcmV2PSR3YXlbY291bnQoJHdheSktMl07IC8v0J/RgNC10LTRi9C00YPRidCw0Y8g0YHRgtCw0L3RhtC40Y8o0LTQu9GPINCy0YDQtdC80LXQvdC4KQoJCSR0aW1lKz0kcGF0aHNbJHByZXZdWyRjdXJyZW50XVsndGltZSddOwoJfQoKCQoJaWYoYXJyYXlfa2V5X2V4aXN0cygkd2hlcmUsJHBhdGhzWyRjdXJyZW50XSkpewoJCSR3YXlbXT0kd2hlcmU7CgkJJHRpbWUrPSRwYXRoc1skY3VycmVudF1bJHdoZXJlXVsndGltZSddOyAvL9CS0YDQtdC80Y8g0YLQtdC60YPRidC10Lkg0YEg0YHQu9C10LTRg9GO0YnQtdC5ICgs0LrQvtGC0L7RgNCw0Y8g0YbQtdC70YwpCgoJCSRhcnJQcmVwWyd3YXknXT0kd2F5OwoJCSRhcnJQcmVwWyd0aW1lJ109JHRpbWU7CgkJJEdMT0JBTFNbJ3dheXMnXVtdPSRhcnJQcmVwOy8v0JTQvtCx0LDQstC70Y/QtdC8INCy0LDRgNC40LDQvdGCINC/0YDQvtGF0L7QtNCwINCyINCy0L7Qt9Cy0YDQsNGJ0LDQtdC80YvQuSDRhNGD0L3QutGG0LjQtdC5INC80LDRgdGB0LjQsgoJfQoJZWxzZXsKCQlmb3JlYWNoICgkcGF0aHNbJGN1cnJlbnRdIGFzICRrPT4kdil7CgkJCSRuZXh0PSRrOwoJCQlpZighaW5fYXJyYXkoJG5leHQsJHdheSkpewoJCQkJJHdheVtdPSRuZXh0OwoJCQkJZmluZF93YXkoJHBhdGhzLCRmcm9tLCR3aGVyZSwkdGltZSwkd2F5KTsKCQkJCWFycmF5X3BvcCgkd2F5KTsKCQkJfQoKCQl9Cgl9CglpZiAoaXNzZXQoJEdMT0JBTFNbJ3dheXMnXSkpCgkJcmV0dXJuICgkR0xPQkFMU1snd2F5cyddKTsKfQoKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCmZ1bmN0aW9uIGZpbmRfc2hvcnRlc3Rfd2F5KCRwYXRocywkZnJvbSwkd2hlcmUsJHRpbWUsJHdheSl7Cgkkd2F5cz1maW5kX3dheSgkcGF0aHMsJGZyb20sJHdoZXJlLCR0aW1lLCR3YXkpOwoKCSRzaG9ydGVzdFsndGltZSddPTA7Cgkkc2hvcnRlc3RbJ3dheSddPScnOwoJCglmb3JlYWNoKCR3YXlzIGFzICRrPT4kdil7CgkJaWYgKCgkc2hvcnRlc3RbJ3RpbWUnXT4kd2F5c1ska11bJ3RpbWUnXSl8fCgkc2hvcnRlc3RbJ3RpbWUnXT09MCkpewoJCQkkc2hvcnRlc3RbJ3RpbWUnXT0kd2F5c1ska11bJ3RpbWUnXTsKCQkJJHNob3J0ZXN0Wyd3YXknXT0kd2F5c1ska11bJ3dheSddOwoJCX0JCQoJfQoKCXJldHVybiAkc2hvcnRlc3Q7Cn0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCmZ1bmN0aW9uIHNob3dfc2hvcnRlc3Rfd2F5KCRwYXRocywkZnJvbSwkd2hlcmUsJHRpbWUsJHdheSwkcG9pbnROYW1lcywkdHJhbnNwb3J0TmFtZSl7Cgkkd2F5cz1maW5kX3Nob3J0ZXN0X3dheSgkcGF0aHMsJGZyb20sJHdoZXJlLCR0aW1lLCR3YXkpOwoJCgkkZmlyc3Q9JHBvaW50TmFtZXNbcmVzZXQoJHdheXNbJ3dheSddKV07CgkkbGFzdD0kcG9pbnROYW1lc1tlbmQoJHdheXNbJ3dheSddKV07CgkKCWVjaG8gItCa0LDQuiDQtNC+0LXRhdCw0YLRjCDQuNC3ICIuJGZpcnN0LiIg0LIgIi4kbGFzdC4iINC30LAgIi4kd2F5c1sndGltZSddLiIg0LzQuNC90YPRglxuIjsKCQoJZm9yKCRpPTA7JGk8Y291bnQoJHdheXNbJ3dheSddKTskaSsrKXsKCQkkY3VycmVudD0kd2F5c1snd2F5J11bJGldOwoJCQoJCQoJCWlmICgkaTwoY291bnQoJHdheXNbJ3dheSddKS0xKSl7CgkJCSRuZXh0PSR3YXlzWyd3YXknXVskaSsxXTsKCQkJZWNobyAiIi4kcG9pbnROYW1lc1skY3VycmVudF0uIlxuCT0+IjsKCQkJZWNobyAkdHJhbnNwb3J0TmFtZVskcGF0aHNbJGN1cnJlbnRdWyRuZXh0XVsnYnknXV0uICIiOwoJCQllY2hvICIg0LfQsCAiLiRwYXRoc1skY3VycmVudF1bJG5leHRdWyd0aW1lJ10uIiDQvNC40L3Rg9GCXG4iOwoJCX0KCQllbHNlCgkJCWVjaG8gJHBvaW50TmFtZXNbJGN1cnJlbnRdLiJcblxuIjsKCX0KfQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8Kc2hvd19zaG9ydGVzdF93YXkoJHBhdGhzLCdwZXQnLCd0ZWgnLDAsbnVsbCwkcG9pbnROYW1lcywkdHJhbnNwb3J0TmFtZSk7CnNob3dfc2hvcnRlc3Rfd2F5KCRwYXRocywndmFzJywnbGV0JywwLG51bGwsJHBvaW50TmFtZXMsJHRyYW5zcG9ydE5hbWUpOw==