<?php // вычисление кратчайшего маршрута алгоритмом Дейкстры
SUBWAY => 'едешь на метро' ,
FOOT => 'идешь пешком' ,
BUS => 'едешь на автобусе'
) ;
$startPoint = 'pet' ; // начало маршрута
$endPoint = 'teh' ; // конец маршрута
$infinity = 1000000 ; //вес маршрута соответствующий бесконечности
'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 initialTime( $pointName , $paths , $pointNames , $infinity ) { //задаём время маршрутов, от выбраной точки до остальных, равным бесконечности
foreach ( $pointNames as $name => $nameLong ) { //время движения от точки до неё самой равно 0
$pathArray [ $name ] = array ( 'totalTime' => $paths [ $pointName ] [ $name ] [ 'time' ] , 'listOfRouts' => array ( 1 => array ( $name , $paths [ $pointName ] [ $name ] [ 'time' ] , $paths [ $pointName ] [ $name ] [ 'by' ] ) ) ) ; }
elseif ( $name == $pointName ) {
$pathArray [ $name ] = array ( 'totalTime' => 0 , 'listOfRouts' => array ( 1 => array ( $name , 0 , 'Ты уже здесь.' ) ) ) ; }
else {
$pathArray [ $name ] = array ( 'totalTime' => $infinity , 'listOfRouts' => array ( ) ) ; }
}
return $pathArray ;
}
function findLocalPointsTime( $routs , $paths , $pointName ) { //ищем время маршрутов от точки до её соседей
$pathArrayInPoint = $routs ;
$pointContacts = $paths [ $pointName ] ;
$pointTime = $routs [ $pointName ] [ 'totalTime' ] ;
foreach ( $pointContacts as $name => $routStat ) {
$newTime = $pointTime + $routStat [ 'time' ] ;
$oldTime = $routs [ $name ] [ 'totalTime' ] ;
if ( $newTime < $oldTime ) {
$pathArrayInPoint [ $name ] [ 'totalTime' ] = $newTime ;
$pathArrayInPoint [ $name ] [ 'listOfRouts' ] = $pathArrayInPoint [ $pointName ] [ 'listOfRouts' ] ;
$pathArrayInPoint [ $name ] [ 'listOfRouts' ] [ ] = array ( $name , $routStat [ 'time' ] , $routStat [ 'by' ] ) ; }
}
return $pathArrayInPoint ;
}
function printRout( $startPoint , $fastRout , $pointNames ) { //вывод информации о маршруте
$start = $startPoint ;
foreach ( $fastRout as $i => $routStat ) {
switch ( $routStat [ 2 ] ) {
case "sub" :
$byWith = "на метро" ;
break ;
case "foot" :
$byWith = "пешком" ;
break ;
case "bus" :
$byWith = "на автобусе" ;
break ;
}
$end = $routStat [ 0 ] ;
echo "От $pointNames [$start ] до $pointNames [$end ] $routStat[1] мин. $byWith \n " ;
$start = $end ;
}
}
//выбираем начальную точку
//задаём время движения до всех остальных точек бесконечным
//обходим все соседние точки и считаем время движения до них
//от каждой соседней точки обходим их соседние точки и считаем обзее время движения до них из первой точки
$listOfPoints = array ( $startPoint ) ; $listOfPoints2 = array ( ) ; $listOfCheckedPoint = array ( ) ;
$routs = initialTime( $startPoint , $paths , $pointNames , $infinity ) ;
$n = 0 ;
while ( isset ( $listOfPoints2 ) && $n < 10 ) { foreach ( $listOfPoints as $i => $name ) {
if ( ! in_array ( $name , $listOfCheckedPoint ) ) { $routs = findLocalPointsTime( $routs , $paths , $name ) ;
$listOfCheckedPoint [ ] = $name ;
$b = $paths [ $name ] ;
foreach ( $b as $name2 => $longName ) {
$listOfPoints2 [ ] = $name2 ;
}
}
}
$listOfPoints = $listOfPoints2 ;
$listOfPoints2 = array ( ) ; $n ++;
}
echo "Путь от $pointNames [$startPoint ] до $pointNames [$endPoint ] займёт {$routs [$endPoint ]['totalTime']} мин.\n " ;
echo "Маршрут:\n " ;
printRout( $startPoint , $routs [ $endPoint ] [ 'listOfRouts' ] , $pointNames ) ;
echo "Приятной поездки!\n " ;
PD9waHAgLy8g0LLRi9GH0LjRgdC70LXQvdC40LUg0LrRgNCw0YLRh9Cw0LnRiNC10LPQviDQvNCw0YDRiNGA0YPRgtCwINCw0LvQs9C+0YDQuNGC0LzQvtC8INCU0LXQudC60YHRgtGA0YsKCgplcnJvcl9yZXBvcnRpbmcoLTEpOwpkZWZpbmUoJ1NVQldBWScsICdzdWInKTsKZGVmaW5lKCdGT09UJywgJ2Zvb3QnKTsKZGVmaW5lKCdCVVMnLCAnYnVzJyk7CiAKJHRyYW5zcG9ydE5hbWUgPSBhcnJheSgKICAgIFNVQldBWSAgPT4gICfQtdC00LXRiNGMINC90LAg0LzQtdGC0YDQvicsCiAgICBGT09UICAgID0+ICAn0LjQtNC10YjRjCDQv9C10YjQutC+0LwnLAogICAgQlVTICAgICA9PiAgJ9C10LTQtdGI0Ywg0L3QsCDQsNCy0YLQvtCx0YPRgdC1JwopOwogCiAKIAokc3RhcnRQb2ludCA9ICdwZXQnOyAvLyDQvdCw0YfQsNC70L4g0LzQsNGA0YjRgNGD0YLQsAokZW5kUG9pbnQgPSAndGVoJzsgLy8g0LrQvtC90LXRhiDQvNCw0YDRiNGA0YPRgtCwCiRpbmZpbml0eSA9IDEwMDAwMDA7IC8v0LLQtdGBINC80LDRgNGI0YDRg9GC0LAg0YHQvtC+0YLQstC10YLRgdGC0LLRg9GO0YnQuNC5INCx0LXRgdC60L7QvdC10YfQvdC+0YHRgtC4CgogCiRwb2ludE5hbWVzID0gYXJyYXkoCiAgICAncGV0JyAgID0+ICAn0YHRgi4g0LwuINCf0LXRgtGA0L7Qs9GA0LDQtNGB0LrQsNGPJywKICAgICdjaGsnICAgPT4gICfRgdGCLiDQvC4g0KfQutCw0LvQvtCy0YHQutCw0Y8nLAogICAgJ2dvcicgICA9PiAgJ9GB0YIuINC8LiDQk9C+0YDRjNC60L7QstGB0LrQsNGPJywKICAgICdzcG8nICAgPT4gICfRgdGCLiDQvC4g0KHQv9C+0YDRgtC40LLQvdCw0Y8nLAogICAgJ3ZhcycgICA9PiAgJ9GB0YIuINC8LiDQktCw0YHQuNC70LXQvtGB0YLRgNC+0LLRgdC60LDRjycsCiAgICAna3JlJyAgID0+ICAn0J/QtdGC0YDQvtC/0LDQstC70L7QstGB0LrQsNGPINC60YDQtdC/0L7RgdGC0YwnLAogICAgJ2xldCcgICA9PiAgJ9Cb0LXRgtC90LjQuSDRgdCw0LQnLAogICAgJ2R2bycgICA9PiAgJ9CU0LLQvtGA0YbQvtCy0LDRjyDQv9C70L7RidCw0LTRjCcsCiAgICAnaXNhJyAgID0+ICAn0JjRgdCw0LrQuNC10LLRgdC60LjQuSDRgdC+0LHQvtGAJywKICAgICdub3YnICAgPT4gICfQndC+0LLQsNGPINCT0L7Qu9C70LDQvdC00LjRjycsCiAgICAncmFzJyAgID0+ICAn0JTQvtC8INCg0LDRgdC60L7Qu9GM0L3QuNC60L7QstCwJywKICAgICdnb3MnICAgPT4gICfQk9C+0YHRgtC40L3Ri9C5INCU0LLQvtGAJywKICAgICdzZW4nICAgPT4gICfQodC10L3QvdCw0Y8g0J/Qu9C+0YnQsNC00YwnLAogICAgJ3ZsYScgICA9PiAgJ9GB0YIuINC8LiDQktC70LDQtNC40LzQuNGA0YHQutCw0Y8nLAogICAgJ3ZpdCcgICA9PiAgJ9CS0LjRgtC10LHRgdC60LjQuSDQstC+0LrQt9Cw0LsnLAogICAgJ3RlaCcgICA9PiAgJ9Ci0LXRhdC90L7Qu9C+0LPQuNGH0LXRgdC60LjQuSDQmNC90YHRgtC40YLRg9GCJwopOwogCiRwYXRocyA9IGFycmF5KAogICAgJ3BldCcgICA9PiAgYXJyYXkoCiAgICAgICAgJ2NoaycgICA9PiAgY2FuR2V0KDEwLCBCVVMpLAogICAgICAgICdnb3InICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAogCiAgICAnY2hrJyAgID0+ICBhcnJheSgKICAgICAgICAncGV0JyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgJ3NwbycgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCiAKICAgICdnb3InICAgPT4gIGFycmF5KAogICAgICAgICdwZXQnICAgPT4gIGNhbkdldCgzLCBCVVMpLAogICAgICAgICdrcmUnICAgPT4gIGNhbkdldCg1LCBGT09UKSwKICAgICAgICAnZ29zJyAgID0+ICBjYW5HZXQoNiwgU1VCV0FZKQogICAgKSwKIAogICAgJ3NwbycgICA9PiAgYXJyYXkoCiAgICAgICAgJ2NoaycgICA9PiAgY2FuR2V0KDMsIFNVQldBWSksCiAgICAgICAgJ3ZhcycgICA9PiAgY2FuR2V0KDEwLCBCVVMpLAogICAgICAgICdzZW4nICAgPT4gIGNhbkdldCg3LCBTVUJXQVkpCiAgICApLAogCiAgICAndmFzJyAgID0+ICBhcnJheSgKICAgICAgICAnc3BvJyAgID0+ICBjYW5HZXQoMTAsIEJVUyksCiAgICAgICAgJ2dvcycgICA9PiAgY2FuR2V0KDcsIFNVQldBWSksCiAgICAgICAgJ25vdicgICA9PiAgY2FuR2V0KDExLCBGT09UKQogICAgKSwKIAogICAgJ2tyZScgICA9PiAgYXJyYXkoCiAgICAgICAgJ2dvcicgICA9PiAgY2FuR2V0KDUsIEZPT1QpCiAgICApLAogCiAgICAnbGV0JyAgID0+ICBhcnJheSgKICAgICAgICAnZHZvJyAgID0+ICBjYW5HZXQoNiwgRk9PVCksCiAgICAgICAgJ2dvcycgICA9PiAgY2FuR2V0KDcsIEZPT1QpCiAgICApLAogCiAgICAnZHZvJyAgID0+ICBhcnJheSgKICAgICAgICAnaXNhJyAgID0+ICBjYW5HZXQoNiwgRk9PVCksCiAgICAgICAgJ2dvcycgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdsZXQnICAgPT4gIGNhbkdldCg2LCBGT09UKQogICAgKSwKIAogICAgJ2lzYScgICA9PiAgYXJyYXkoCiAgICAgICAgJ2R2bycgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdub3YnICAgPT4gIGNhbkdldCg1LCBGT09UKQogICAgKSwKIAogICAgJ25vdicgICA9PiAgYXJyYXkoCiAgICAgICAgJ3ZhcycgICA9PiAgY2FuR2V0KDExLCBGT09UKSwKICAgICAgICAnaXNhJyAgID0+ICBjYW5HZXQoNSwgRk9PVCksCiAgICAgICAgJ3JhcycgICA9PiAgY2FuR2V0KDcsIEJVUykKICAgICksCiAKICAgICdyYXMnICAgPT4gIGFycmF5KAogICAgICAgICdub3YnICAgPT4gIGNhbkdldCg3LCBCVVMpLAogICAgICAgICdzZW4nICAgPT4gIGNhbkdldCgzLCBGT09UKQogICAgKSwKIAogICAgJ2dvcycgICA9PiAgYXJyYXkoCiAgICAgICAgJ3ZhcycgICA9PiAgY2FuR2V0KDcsIFNVQldBWSksCiAgICAgICAgJ3NlbicgICA9PiAgY2FuR2V0KDMsIFNVQldBWSksCiAgICAgICAgJ2R2bycgICA9PiAgY2FuR2V0KDYsIEZPT1QpLAogICAgICAgICdnb3InICAgPT4gIGNhbkdldCg2LCBTVUJXQVkpLAogICAgICAgICdsZXQnICAgPT4gIGNhbkdldCg3LCBGT09UKSwKICAgICAgICAndmxhJyAgID0+ICBjYW5HZXQoNywgRk9PVCkgICAgICAgIAogICAgKSwKIAogICAgJ3NlbicgICA9PiAgYXJyYXkoCiAgICAgICAgJ3JhcycgICA9PiAgY2FuR2V0KDMsIEZPT1QpLAogICAgICAgICdzcG8nICAgPT4gIGNhbkdldCg3LCBTVUJXQVkpLAogICAgICAgICdnb3MnICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpLAogICAgICAgICd2bGEnICAgPT4gIGNhbkdldCg0LCBTVUJXQVkpLAogICAgICAgICd2aXQnICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpLAogICAgICAgICd0ZWgnICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAogCiAgICAndmxhJyAgID0+ICBhcnJheSgKICAgICAgICAnc2VuJyAgID0+ICBjYW5HZXQoNCwgU1VCV0FZKSwKICAgICAgICAnZ29zJyAgID0+ICBjYW5HZXQoNywgRk9PVCksCiAgICAgICAgJ3ZpdCcgICA9PiAgY2FuR2V0KDMsIFNVQldBWSkKICAgICksCiAKICAgICd2aXQnICAgPT4gIGFycmF5KAogICAgICAgICdzZW4nICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpLAogICAgICAgICd0ZWgnICAgPT4gIGNhbkdldCgyLCBTVUJXQVkpLAogICAgICAgICd2bGEnICAgPT4gIGNhbkdldCgzLCBTVUJXQVkpCiAgICApLAogCiAgICAndGVoJyAgID0+ICBhcnJheSgKICAgICAgICAnc2VuJyAgID0+ICBjYW5HZXQoMywgU1VCV0FZKSwKICAgICAgICAndml0JyAgID0+ICBjYW5HZXQoMiwgU1VCV0FZKSAgICAgICAgCiAgICApCik7CiAKLyog0KfRgtC+0LHRiyDQvdC1INC/0LjRgdCw0YLRjCDQvNC90L7Qs9C+INGA0LDQtyBhcnJheSgndGltZScgPT4gLi4uLCAnYnknID0+IC4uLiksINC40YHQv9C+0LvRjNC30YPQtdC8INGE0YPQvdC60YbQuNGOLiAKICAgIMKrY2FuR2V0wrsg0L/QtdGA0LXQstC+0LTQuNGC0YHRjyDQutCw0LogwqvQvNC+0LbQvdC+INC/0L7Qv9Cw0YHRgtGMwrsgKi8KZnVuY3Rpb24gY2FuR2V0KCR0aW1lLCAkYnlXaGF0KSB7CiAgICByZXR1cm4gYXJyYXkoJ3RpbWUnICAgICA9PiAgJHRpbWUsICdieScgPT4gICRieVdoYXQpOwp9CgpmdW5jdGlvbiBpbml0aWFsVGltZSgkcG9pbnROYW1lLCRwYXRocywkcG9pbnROYW1lcywkaW5maW5pdHkpewkvL9C30LDQtNCw0ZHQvCDQstGA0LXQvNGPINC80LDRgNGI0YDRg9GC0L7Qsiwg0L7RgiDQstGL0LHRgNCw0L3QvtC5INGC0L7Rh9C60Lgg0LTQviDQvtGB0YLQsNC70YzQvdGL0YUsINGA0LDQstC90YvQvCDQsdC10YHQutC+0L3QtdGH0L3QvtGB0YLQuAoJZm9yZWFjaCgkcG9pbnROYW1lcyBhcyAkbmFtZT0+JG5hbWVMb25nKXsJCQkJCS8v0LLRgNC10LzRjyDQtNCy0LjQttC10L3QuNGPINC+0YIg0YLQvtGH0LrQuCDQtNC+INC90LXRkSDRgdCw0LzQvtC5INGA0LDQstC90L4gMAoJCWlmIChhcnJheV9rZXlfZXhpc3RzKCRuYW1lLCRwYXRoc1skcG9pbnROYW1lXSkpewoJCQkkcGF0aEFycmF5WyRuYW1lXSA9IGFycmF5KCd0b3RhbFRpbWUnPT4kcGF0aHNbJHBvaW50TmFtZV1bJG5hbWVdWyd0aW1lJ10sJ2xpc3RPZlJvdXRzJz0+YXJyYXkoMT0+YXJyYXkoJG5hbWUsJHBhdGhzWyRwb2ludE5hbWVdWyRuYW1lXVsndGltZSddLCRwYXRoc1skcG9pbnROYW1lXVskbmFtZV1bJ2J5J10pKSk7CQoJCX0KCQllbHNlaWYoJG5hbWUgPT0gJHBvaW50TmFtZSl7CgkJCSRwYXRoQXJyYXlbJG5hbWVdID0gYXJyYXkoJ3RvdGFsVGltZSc9PjAsJ2xpc3RPZlJvdXRzJz0+YXJyYXkoMT0+YXJyYXkoJG5hbWUsMCwn0KLRiyDRg9C20LUg0LfQtNC10YHRjC4nKSkpOwkKCQl9CgkJZWxzZXsKCQkJJHBhdGhBcnJheVskbmFtZV0gPSBhcnJheSgndG90YWxUaW1lJz0+JGluZmluaXR5LCdsaXN0T2ZSb3V0cyc9PmFycmF5KCkpOwkJCgkJfQoJfQoJcmV0dXJuICRwYXRoQXJyYXk7Cn0KZnVuY3Rpb24gZmluZExvY2FsUG9pbnRzVGltZSgkcm91dHMsJHBhdGhzLCRwb2ludE5hbWUpeyAJLy/QuNGJ0LXQvCDQstGA0LXQvNGPINC80LDRgNGI0YDRg9GC0L7QsiDQvtGCINGC0L7Rh9C60Lgg0LTQviDQtdGRINGB0L7RgdC10LTQtdC5CgkkcGF0aEFycmF5SW5Qb2ludCA9ICRyb3V0czsKCSRwb2ludENvbnRhY3RzID0gJHBhdGhzWyRwb2ludE5hbWVdOwoJJHBvaW50VGltZSA9ICRyb3V0c1skcG9pbnROYW1lXVsndG90YWxUaW1lJ107Cglmb3JlYWNoKCRwb2ludENvbnRhY3RzIGFzICRuYW1lPT4kcm91dFN0YXQpewoJCSRuZXdUaW1lID0gJHBvaW50VGltZSArICRyb3V0U3RhdFsndGltZSddOwoJCSRvbGRUaW1lID0gJHJvdXRzWyRuYW1lXVsndG90YWxUaW1lJ107CgkJaWYoJG5ld1RpbWU8JG9sZFRpbWUpewoJCQkkcGF0aEFycmF5SW5Qb2ludFskbmFtZV1bJ3RvdGFsVGltZSddID0gJG5ld1RpbWU7CgkJCSRwYXRoQXJyYXlJblBvaW50WyRuYW1lXVsnbGlzdE9mUm91dHMnXSA9ICRwYXRoQXJyYXlJblBvaW50WyRwb2ludE5hbWVdWydsaXN0T2ZSb3V0cyddOyAgCgkJCSRwYXRoQXJyYXlJblBvaW50WyRuYW1lXVsnbGlzdE9mUm91dHMnXVtdID0gYXJyYXkoJG5hbWUsJHJvdXRTdGF0Wyd0aW1lJ10sJHJvdXRTdGF0WydieSddKTsgCgkJfQoJfQoJcmV0dXJuICRwYXRoQXJyYXlJblBvaW50Owp9CgpmdW5jdGlvbiBwcmludFJvdXQoJHN0YXJ0UG9pbnQsJGZhc3RSb3V0LCRwb2ludE5hbWVzKXsJCS8v0LLRi9Cy0L7QtCDQuNC90YTQvtGA0LzQsNGG0LjQuCDQviDQvNCw0YDRiNGA0YPRgtC1Cgkkc3RhcnQgPSAkc3RhcnRQb2ludDsKCWZvcmVhY2goJGZhc3RSb3V0IGFzICRpPT4kcm91dFN0YXQpewoJCXN3aXRjaCAoJHJvdXRTdGF0WzJdKXsKCQkJY2FzZSAic3ViIjoKCQkJCSRieVdpdGggPSAi0L3QsCDQvNC10YLRgNC+IjsKCQkJCWJyZWFrOwoJCQljYXNlICJmb290IjoKCQkJCSRieVdpdGggPSAi0L/QtdGI0LrQvtC8IjsKCQkJCWJyZWFrOwoJCQljYXNlICJidXMiOgkJCgkJCQkkYnlXaXRoID0gItC90LAg0LDQstGC0L7QsdGD0YHQtSI7CgkJCQlicmVhazsKCQl9CgkJJGVuZCA9ICRyb3V0U3RhdFswXTsKCQllY2hvICLQntGCICRwb2ludE5hbWVzWyRzdGFydF0g0LTQviAkcG9pbnROYW1lc1skZW5kXSAkcm91dFN0YXRbMV0g0LzQuNC9LiAkYnlXaXRoXG4iOwoJCSRzdGFydCA9ICRlbmQ7Cgl9Cn0KCi8v0LLRi9Cx0LjRgNCw0LXQvCDQvdCw0YfQsNC70YzQvdGD0Y4g0YLQvtGH0LrRgwovL9C30LDQtNCw0ZHQvCDQstGA0LXQvNGPINC00LLQuNC20LXQvdC40Y8g0LTQviDQstGB0LXRhSDQvtGB0YLQsNC70YzQvdGL0YUg0YLQvtGH0LXQuiDQsdC10YHQutC+0L3QtdGH0L3Ri9C8Ci8v0L7QsdGF0L7QtNC40Lwg0LLRgdC1INGB0L7RgdC10LTQvdC40LUg0YLQvtGH0LrQuCDQuCDRgdGH0LjRgtCw0LXQvCDQstGA0LXQvNGPINC00LLQuNC20LXQvdC40Y8g0LTQviDQvdC40YUKLy/QvtGCINC60LDQttC00L7QuSDRgdC+0YHQtdC00L3QtdC5INGC0L7Rh9C60Lgg0L7QsdGF0L7QtNC40Lwg0LjRhSDRgdC+0YHQtdC00L3QuNC1INGC0L7Rh9C60Lgg0Lgg0YHRh9C40YLQsNC10Lwg0L7QsdC30LXQtSDQstGA0LXQvNGPINC00LLQuNC20LXQvdC40Y8g0LTQviDQvdC40YUg0LjQtyDQv9C10YDQstC+0Lkg0YLQvtGH0LrQuAoKJGxpc3RPZlBvaW50cyA9IGFycmF5KCRzdGFydFBvaW50KTsKJGxpc3RPZlBvaW50czIgPSBhcnJheSgpOwokbGlzdE9mQ2hlY2tlZFBvaW50ID0gYXJyYXkoKTsKCiRyb3V0cyA9IGluaXRpYWxUaW1lKCRzdGFydFBvaW50LCRwYXRocywkcG9pbnROYW1lcywkaW5maW5pdHkpOwokbiA9IDA7CndoaWxlIChpc3NldCgkbGlzdE9mUG9pbnRzMikmJiRuPDEwKXsKCWZvcmVhY2goJGxpc3RPZlBvaW50cyBhcyAkaT0+JG5hbWUpewoJCWlmICghaW5fYXJyYXkoJG5hbWUsJGxpc3RPZkNoZWNrZWRQb2ludCkpewoJCQkkcm91dHMgPSBmaW5kTG9jYWxQb2ludHNUaW1lKCRyb3V0cywkcGF0aHMsJG5hbWUpOwkKCQkJJGxpc3RPZkNoZWNrZWRQb2ludFtdID0gJG5hbWU7CgkJCSRiID0gJHBhdGhzWyRuYW1lXTsKCQkJZm9yZWFjaCgkYiBhcyAkbmFtZTI9PiRsb25nTmFtZSl7CgkJCQkkbGlzdE9mUG9pbnRzMltdID0gJG5hbWUyOwoJCQl9CgkJfQoJfQkKCSRsaXN0T2ZQb2ludHMgPSAkbGlzdE9mUG9pbnRzMjsKCSRsaXN0T2ZQb2ludHMyID0gYXJyYXkoKTsKCSRuKys7Cn0KZWNobyAi0J/Rg9GC0Ywg0L7RgiAkcG9pbnROYW1lc1skc3RhcnRQb2ludF0g0LTQviAkcG9pbnROYW1lc1skZW5kUG9pbnRdINC30LDQudC80ZHRgiB7JHJvdXRzWyRlbmRQb2ludF1bJ3RvdGFsVGltZSddfSDQvNC40L0uXG4iOwplY2hvICLQnNCw0YDRiNGA0YPRgjpcbiI7CnByaW50Um91dCgkc3RhcnRQb2ludCwkcm91dHNbJGVuZFBvaW50XVsnbGlzdE9mUm91dHMnXSwkcG9pbnROYW1lcyk7CmVjaG8gItCf0YDQuNGP0YLQvdC+0Lkg0L/QvtC10LfQtNC60LghXG4iOwoKCgoK