<?php
abstract class Question
{
protected $text ;
protected $points ;
protected $correctAnswer ;
protected $hint ;
abstract function getAsString( ) : string;
abstract function checkAnswer
( $answer ) : array ;
// Возвращает вопрос
public function getQuestionText( ) : string
{
$text = $this -> text ;
return $text ;
}
// Возвращает количество баллов за правильный ответ
public function getPoints( ) : int
{
$points = $this -> points ;
return $points ;
}
// Возвращает подсказку
public function getQuestionHint( ) : string
{
$hint = $this -> hint ;
return $hint ;
}
}
class MultipleChoiceQuestion extends Question
{
protected $answers ;
protected $almostCorrectAnswer ;
public function __construct
( string
$text , float
$points , array $answers , string
$correctAnswer , string
$hint ) {
$this -> text = $text ;
$this -> points = $points ;
$this -> answers = $answers ;
$this -> correctAnswer = $correctAnswer ;
$this -> hint = $hint ;
}
// Функция добавляющая почти корректный ответ
public function addAlmostCorrectAnswer( $almostCorrectAnswer )
{
$this -> almostCorrectAnswer = $almostCorrectAnswer ;
}
// Функция отдающая строку со списком вопросов
public function getAsString( ) : string
{
$string = "{$this->text} \n Варианты ответов:\n " ;
foreach ( $this -> answers as $letter => $answer ) {
$string = $string . "{$letter} . {$answer} \n " ;
}
return $string ;
}
/* Функция получает на вход ответ.
Проверяет его, учитывая почти правильный вариант ответа.
Возвращает в массиве результаты проверки */
public function checkAnswer
( $answer ) : array {
$isCorrect = 0 ;
$isAlmostCorrect = 0 ;
if ( $answer == $this -> correctAnswer ) {
$isCorrect = 1 ;
} elseif ( $answer == $this -> almostCorrectAnswer ) {
$isAlmostCorrect = 1 ;
}
return array ( $isCorrect , $isAlmostCorrect ) ; }
}
class NumericalQuestion extends Question
{
protected $deviation ;
function __construct( string $text , string $hint , float $points , float $correctAnswer , float $deviation = 0 )
{
$this -> text = $text ;
$this -> points = $points ;
$this -> correctAnswer = $correctAnswer ;
$this -> deviation = $deviation ;
$this -> hint = $hint ;
}
// Функция возвращает строку со списком вопросов
public function getAsString( ) : string
{
return "{$this->text} \n " ;
}
/* Функция получает ответ. Проверяет его с учетом возможного отклонения.
Возвращает в массиве результат проверки. */
public function checkAnswer
( $answer ) : array {
$isCorrect = 0 ;
if ( $answer == $this -> correctAnswer or
$this -> deviation > abs ( $this -> correctAnswer - $answer ) ) { $isCorrect = 1 ;
}
return array ( $isCorrect , $isAlmostCorrect = 0 ) ; }
}
// Функция создающая массив с вопросами
function createQuestions( ) {
$questions = [ ] ;
$text = 'Какая планета располагается четвертой по счету от Солнца?' ;
$answers = array ( 'a' => 'Венера' , 'b' => 'Марс' , 'c' => 'Юпитер' , 'd' => 'Меркурий' ) ; $hint = 'Одноименное название носит шоколадный батончик.' ;
$q = new MultipleChoiceQuestion( $text , 10 , $answers , 'b' , $hint ) ;
$questions [ ] = $q ;
$text = 'Какой город является столицей Великобритании?' ;
$answers = array ( 'a' => 'Париж' , 'b' => 'Москва' , 'c' => 'Нью-Йорк' , 'd' => 'Лондон' ) ; $hint = '%Городнейм% из кэпитал оф грейт британ.' ;
$q = new MultipleChoiceQuestion( $text , 5 , $answers , 'd' , $hint ) ;
$questions [ ] = $q ;
$text = 'Кто придумал теорию относительности?' ;
$answers = array ( 'a' => 'Джон Леннон' , 'b' => 'Джим Моррисон' , 'c' => 'Альберт Эйнштейн' , 'd' => 'Исаак Ньютон' ) ; $hint = 'Этим парнем был...' ;
$q = new MultipleChoiceQuestion( $text , 30 , $answers , 'c' , $hint ) ;
$q -> addAlmostCorrectAnswer ( 'b' ) ;
$questions [ ] = $q ;
$hint = 'Попробуй еще раз, дружок-пирожок!' ;
$q = new NumericalQuestion( 'Чему равна скорость света в км/с?' , $hint , 15 , 299792 , 210 ) ;
$questions [ ] = $q ;
$hint = 'Между 2 и 4, подумой.' ;
$q = new NumericalQuestion( 'Чему равно число Пи?' , $hint , 30 , 3.14 , 0.01 ) ;
$questions [ ] = $q ;
$hint = 'Сычёв, ты отчислен!' ;
$q = new NumericalQuestion( 'В каком году закончилась вторая мировая война?' , $hint , 10 , 1945 ) ;
$questions [ ] = $q ;
return $questions ;
}
// Функция выводящая список вопросов с вариантами ответов
function printQuestions( $questions ) {
$number = 1 ;
foreach ( $questions as $question ) {
echo "\n {$number} . " ;
echo $question -> getAsString ( ) ;
$number ++;
}
}
/* Функция получает массивы вопросов и ответов. Проверяет ответы,
считает число баллов и печатает вопросы на которые был дан неправильный ответ. */
function checkAnswers( $questions , $answers )
{
die ( "Число ответов и вопросов не совпадает\n " ) ; }
$pointsTotal = 0 ;
$pointsMax = 0 ;
$correctAnswers = 0 ;
$totalQuestions = count ( $questions ) ;
for ( $i = 0 ; $i < count ( $questions ) ; $i ++ ) {
$question = $questions [ $i ] ;
$answer = $answers [ $i ] ;
list ( $isCorrect , $isAlmostCorrect ) = $question -> checkAnswer ( $answer ) ; $points = $question -> getPoints ( ) ;
$pointsMax += $points ;
if ( $isCorrect ) {
$correctAnswers ++;
$pointsTotal += $points ;
} elseif ( $isAlmostCorrect ) {
$correctAnswers ++;
$pointsTotal += $points / 2 ;
} else {
$number = $i + 1 ;
echo "\n Неправильный ответ на вопрос №{$number} ({$question->getQuestionText ()})\n " ;
echo "\n Подсказка: {$question->getQuestionHint ()}\n " ;
}
}
echo "\n Правильных ответов: {$correctAnswers} из {$totalQuestions} , баллов набрано: $pointsTotal из $pointsMax \n " ;
}
$questions = createQuestions( ) ;
printQuestions( $questions ) ;
checkAnswers
( $questions , array ( 'b' , 'd' , 'b' , 299792 , 3.14444 , 1944 ) ) ;
PD9waHAKCmVycm9yX3JlcG9ydGluZyhFX0FMTCk7CgphYnN0cmFjdCBjbGFzcyBRdWVzdGlvbgp7Cglwcm90ZWN0ZWQgJHRleHQ7Cglwcm90ZWN0ZWQgJHBvaW50czsKCXByb3RlY3RlZCAkY29ycmVjdEFuc3dlcjsKCXByb3RlY3RlZCAkaGludDsKCglhYnN0cmFjdCBmdW5jdGlvbiBnZXRBc1N0cmluZygpOiBzdHJpbmc7CglhYnN0cmFjdCBmdW5jdGlvbiBjaGVja0Fuc3dlcigkYW5zd2VyKTogYXJyYXk7CgoJLy8g0JLQvtC30LLRgNCw0YnQsNC10YIg0LLQvtC/0YDQvtGBCglwdWJsaWMgZnVuY3Rpb24gZ2V0UXVlc3Rpb25UZXh0KCk6IHN0cmluZwoJewoJCSR0ZXh0ID0gJHRoaXMtPnRleHQ7CgkJcmV0dXJuICR0ZXh0OwoJfQoKCS8vINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINC60L7Qu9C40YfQtdGB0YLQstC+INCx0LDQu9C70L7QsiDQt9CwINC/0YDQsNCy0LjQu9GM0L3Ri9C5INC+0YLQstC10YIKCXB1YmxpYyBmdW5jdGlvbiBnZXRQb2ludHMoKTogaW50Cgl7CgkJJHBvaW50cyA9ICR0aGlzLT5wb2ludHM7CgkJcmV0dXJuICRwb2ludHM7Cgl9CgoJLy8g0JLQvtC30LLRgNCw0YnQsNC10YIg0L/QvtC00YHQutCw0LfQutGDCglwdWJsaWMgZnVuY3Rpb24gZ2V0UXVlc3Rpb25IaW50KCk6IHN0cmluZwoJewoJCSRoaW50ID0gJHRoaXMtPmhpbnQ7CgkJcmV0dXJuICRoaW50OwoJfQp9CgpjbGFzcyBNdWx0aXBsZUNob2ljZVF1ZXN0aW9uIGV4dGVuZHMgUXVlc3Rpb24KewogICAgcHJvdGVjdGVkICRhbnN3ZXJzOwogICAgcHJvdGVjdGVkICRhbG1vc3RDb3JyZWN0QW5zd2VyOwoKCXB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdChzdHJpbmcgJHRleHQsIGZsb2F0ICRwb2ludHMsIGFycmF5ICRhbnN3ZXJzLCBzdHJpbmcgJGNvcnJlY3RBbnN3ZXIsIHN0cmluZyAkaGludCkKCXsKCQkkdGhpcy0+dGV4dCA9ICR0ZXh0OwoJCSR0aGlzLT5wb2ludHMgPSAkcG9pbnRzOwoJCSR0aGlzLT5hbnN3ZXJzID0gJGFuc3dlcnM7CgkJJHRoaXMtPmNvcnJlY3RBbnN3ZXIgPSAkY29ycmVjdEFuc3dlcjsKCQkkdGhpcy0+aGludCA9ICRoaW50OwoJfQoKCS8vINCk0YPQvdC60YbQuNGPINC00L7QsdCw0LLQu9GP0Y7RidCw0Y8g0L/QvtGH0YLQuCDQutC+0YDRgNC10LrRgtC90YvQuSDQvtGC0LLQtdGCCglwdWJsaWMgZnVuY3Rpb24gYWRkQWxtb3N0Q29ycmVjdEFuc3dlcigkYWxtb3N0Q29ycmVjdEFuc3dlcikKCXsKCQkkdGhpcy0+YWxtb3N0Q29ycmVjdEFuc3dlciA9ICRhbG1vc3RDb3JyZWN0QW5zd2VyOwoJfQoKCS8vINCk0YPQvdC60YbQuNGPINC+0YLQtNCw0Y7RidCw0Y8g0YHRgtGA0L7QutGDINGB0L4g0YHQv9C40YHQutC+0Lwg0LLQvtC/0YDQvtGB0L7QsgoJcHVibGljIGZ1bmN0aW9uIGdldEFzU3RyaW5nKCk6IHN0cmluZwoJewoJCSRzdHJpbmcgPSAieyR0aGlzLT50ZXh0fVxu0JLQsNGA0LjQsNC90YLRiyDQvtGC0LLQtdGC0L7QsjpcbiI7CgoJCWZvcmVhY2ggKCR0aGlzLT5hbnN3ZXJzIGFzICRsZXR0ZXIgPT4gJGFuc3dlcikgewoJCQkkc3RyaW5nID0gJHN0cmluZy4ieyRsZXR0ZXJ9LiB7JGFuc3dlcn1cbiI7CgkJfQoKCQlyZXR1cm4gJHN0cmluZzsKCX0KCgkvKiDQpNGD0L3QutGG0LjRjyDQv9C+0LvRg9GH0LDQtdGCINC90LAg0LLRhdC+0LQg0L7RgtCy0LXRgi4gCgnQn9GA0L7QstC10YDRj9C10YIg0LXQs9C+LCDRg9GH0LjRgtGL0LLQsNGPINC/0L7Rh9GC0Lgg0L/RgNCw0LLQuNC70YzQvdGL0Lkg0LLQsNGA0LjQsNC90YIg0L7RgtCy0LXRgtCwLiAKCdCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINCyINC80LDRgdGB0LjQstC1INGA0LXQt9GD0LvRjNGC0LDRgtGLINC/0YDQvtCy0LXRgNC60LggKi8KCglwdWJsaWMgZnVuY3Rpb24gY2hlY2tBbnN3ZXIoJGFuc3dlcik6IGFycmF5Cgl7CgkJJGlzQ29ycmVjdCA9IDA7CgkJJGlzQWxtb3N0Q29ycmVjdCA9IDA7CgoJCWlmICgkYW5zd2VyID09ICR0aGlzLT5jb3JyZWN0QW5zd2VyKSB7CgkJCSRpc0NvcnJlY3QgPSAxOwoJCX0gZWxzZWlmICgkYW5zd2VyID09ICR0aGlzLT5hbG1vc3RDb3JyZWN0QW5zd2VyKSB7CgkJCSRpc0FsbW9zdENvcnJlY3QgPSAxOwoJCX0KCgkJcmV0dXJuIGFycmF5KCRpc0NvcnJlY3QsICRpc0FsbW9zdENvcnJlY3QpOwoJfQoKfQoKY2xhc3MgTnVtZXJpY2FsUXVlc3Rpb24gZXh0ZW5kcyBRdWVzdGlvbgp7Cglwcm90ZWN0ZWQgJGRldmlhdGlvbjsKCglmdW5jdGlvbiBfX2NvbnN0cnVjdChzdHJpbmcgJHRleHQsIHN0cmluZyAkaGludCwgZmxvYXQgJHBvaW50cywgZmxvYXQgJGNvcnJlY3RBbnN3ZXIsIGZsb2F0ICRkZXZpYXRpb24gPSAwKQoJewoJCSR0aGlzLT50ZXh0ID0gJHRleHQ7CgkJJHRoaXMtPnBvaW50cyA9ICRwb2ludHM7CgkJJHRoaXMtPmNvcnJlY3RBbnN3ZXIgPSAkY29ycmVjdEFuc3dlcjsKCQkkdGhpcy0+ZGV2aWF0aW9uID0gJGRldmlhdGlvbjsKCQkkdGhpcy0+aGludCA9ICRoaW50OwoJfQoKCS8vINCk0YPQvdC60YbQuNGPINCy0L7Qt9Cy0YDQsNGJ0LDQtdGCINGB0YLRgNC+0LrRgyDRgdC+INGB0L/QuNGB0LrQvtC8INCy0L7Qv9GA0L7RgdC+0LIKCXB1YmxpYyBmdW5jdGlvbiBnZXRBc1N0cmluZygpOiBzdHJpbmcKCXsKCQlyZXR1cm4gInskdGhpcy0+dGV4dH1cbiI7Cgl9CgoJLyog0KTRg9C90LrRhtC40Y8g0L/QvtC70YPRh9Cw0LXRgiDQvtGC0LLQtdGCLiDQn9GA0L7QstC10YDRj9C10YIg0LXQs9C+INGBINGD0YfQtdGC0L7QvCDQstC+0LfQvNC+0LbQvdC+0LPQviDQvtGC0LrQu9C+0L3QtdC90LjRjy4KCdCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINCyINC80LDRgdGB0LjQstC1INGA0LXQt9GD0LvRjNGC0LDRgiDQv9GA0L7QstC10YDQutC4LiAqLwoKCXB1YmxpYyBmdW5jdGlvbiBjaGVja0Fuc3dlcigkYW5zd2VyKTogYXJyYXkKCXsKCQkkaXNDb3JyZWN0ID0gMDsKCgkJaWYgKCRhbnN3ZXIgPT0gJHRoaXMtPmNvcnJlY3RBbnN3ZXIgb3IgJHRoaXMtPmRldmlhdGlvbiA+IGFicygkdGhpcy0+Y29ycmVjdEFuc3dlciAtICRhbnN3ZXIpKSB7CgkJCSRpc0NvcnJlY3QgPSAxOwoJCX0KCiAgICAgICAgcmV0dXJuIGFycmF5KCRpc0NvcnJlY3QsICRpc0FsbW9zdENvcnJlY3QgPSAwKTsKCX0KCn0KCi8vINCk0YPQvdC60YbQuNGPINGB0L7Qt9C00LDRjtGJ0LDRjyDQvNCw0YHRgdC40LIg0YEg0LLQvtC/0YDQvtGB0LDQvNC4CmZ1bmN0aW9uIGNyZWF0ZVF1ZXN0aW9ucygpIHsKCgkkcXVlc3Rpb25zID0gW107CgoJJHRleHQgPSAn0JrQsNC60LDRjyDQv9C70LDQvdC10YLQsCDRgNCw0YHQv9C+0LvQsNCz0LDQtdGC0YHRjyDRh9C10YLQstC10YDRgtC+0Lkg0L/QviDRgdGH0LXRgtGDINC+0YIg0KHQvtC70L3RhtCwPyc7CgkkYW5zd2VycyA9IGFycmF5KCdhJyA9PiAn0JLQtdC90LXRgNCwJywgJ2InID0+ICfQnNCw0YDRgScsICdjJyA9PiAn0K7Qv9C40YLQtdGAJywgJ2QnID0+ICfQnNC10YDQutGD0YDQuNC5Jyk7CgkkaGludCA9ICfQntC00L3QvtC40LzQtdC90L3QvtC1INC90LDQt9Cy0LDQvdC40LUg0L3QvtGB0LjRgiDRiNC+0LrQvtC70LDQtNC90YvQuSDQsdCw0YLQvtC90YfQuNC6Lic7CgkkcSA9IG5ldyBNdWx0aXBsZUNob2ljZVF1ZXN0aW9uKCR0ZXh0LCAxMCwgJGFuc3dlcnMsICdiJywgJGhpbnQpOwoKCSRxdWVzdGlvbnNbXSA9ICRxOwoKCSR0ZXh0ID0gJ9Ca0LDQutC+0Lkg0LPQvtGA0L7QtCDRj9Cy0LvRj9C10YLRgdGPINGB0YLQvtC70LjRhtC10Lkg0JLQtdC70LjQutC+0LHRgNC40YLQsNC90LjQuD8nOwoJJGFuc3dlcnMgPSBhcnJheSgnYScgPT4gJ9Cf0LDRgNC40LYnLCAnYicgPT4gJ9Cc0L7RgdC60LLQsCcsICdjJyA9PiAn0J3RjNGOLdCZ0L7RgNC6JywgJ2QnID0+ICfQm9C+0L3QtNC+0L0nKTsKCSRoaW50ID0gJyXQk9C+0YDQvtC00L3QtdC50LwlINC40Lcg0LrRjdC/0LjRgtCw0Lsg0L7RhCDQs9GA0LXQudGCINCx0YDQuNGC0LDQvS4nOwoJJHEgPSBuZXcgTXVsdGlwbGVDaG9pY2VRdWVzdGlvbigkdGV4dCwgNSwgJGFuc3dlcnMsICdkJywgJGhpbnQpOwoKCSRxdWVzdGlvbnNbXSA9ICRxOwoKCSR0ZXh0ID0gJ9Ca0YLQviDQv9GA0LjQtNGD0LzQsNC7INGC0LXQvtGA0LjRjiDQvtGC0L3QvtGB0LjRgtC10LvRjNC90L7RgdGC0Lg/JzsKCSRhbnN3ZXJzID0gYXJyYXkoJ2EnID0+ICfQlNC20L7QvSDQm9C10L3QvdC+0L0nLCAnYicgPT4gJ9CU0LbQuNC8INCc0L7RgNGA0LjRgdC+0L0nLCAnYycgPT4gJ9CQ0LvRjNCx0LXRgNGCINCt0LnQvdGI0YLQtdC50L0nLCAnZCcgPT4gJ9CY0YHQsNCw0Log0J3RjNGO0YLQvtC9Jyk7CgkkaGludCA9ICfQrdGC0LjQvCDQv9Cw0YDQvdC10Lwg0LHRi9C7Li4uJzsKCSRxID0gbmV3IE11bHRpcGxlQ2hvaWNlUXVlc3Rpb24oJHRleHQsIDMwLCAkYW5zd2VycywgJ2MnLCAkaGludCk7CgkkcS0+YWRkQWxtb3N0Q29ycmVjdEFuc3dlcignYicpOwoKCSRxdWVzdGlvbnNbXSA9ICRxOwoKCSRoaW50ID0gJ9Cf0L7Qv9GA0L7QsdGD0Lkg0LXRidC1INGA0LDQtywg0LTRgNGD0LbQvtC6LdC/0LjRgNC+0LbQvtC6ISc7CgkkcSA9IG5ldyBOdW1lcmljYWxRdWVzdGlvbign0KfQtdC80YMg0YDQsNCy0L3QsCDRgdC60L7RgNC+0YHRgtGMINGB0LLQtdGC0LAg0LIg0LrQvC/RgT8nLCAkaGludCwgMTUsIDI5OTc5MiwgMjEwKTsKCgkkcXVlc3Rpb25zW10gPSAkcTsKCgkkaGludCA9ICfQnNC10LbQtNGDIDIg0LggNCwg0L/QvtC00YPQvNC+0LkuJzsKCSRxID0gbmV3IE51bWVyaWNhbFF1ZXN0aW9uKCfQp9C10LzRgyDRgNCw0LLQvdC+INGH0LjRgdC70L4g0J/QuD8nLCAkaGludCwgMzAsIDMuMTQsIDAuMDEpOwoKCSRxdWVzdGlvbnNbXSA9ICRxOwoKCSRoaW50ID0gJ9Ch0YvRh9GR0LIsINGC0Ysg0L7RgtGH0LjRgdC70LXQvSEnOwoJJHEgPSBuZXcgTnVtZXJpY2FsUXVlc3Rpb24oJ9CSINC60LDQutC+0Lwg0LPQvtC00YMg0LfQsNC60L7QvdGH0LjQu9Cw0YHRjCDQstGC0L7RgNCw0Y8g0LzQuNGA0L7QstCw0Y8g0LLQvtC50L3QsD8nLCAkaGludCwgMTAsIDE5NDUpOwoKCSRxdWVzdGlvbnNbXSA9ICRxOwoKCXJldHVybiAkcXVlc3Rpb25zOwp9CgovLyDQpNGD0L3QutGG0LjRjyDQstGL0LLQvtC00Y/RidCw0Y8g0YHQv9C40YHQvtC6INCy0L7Qv9GA0L7RgdC+0LIg0YEg0LLQsNGA0LjQsNC90YLQsNC80Lgg0L7RgtCy0LXRgtC+0LIKZnVuY3Rpb24gcHJpbnRRdWVzdGlvbnMoJHF1ZXN0aW9ucykgewoKCSRudW1iZXIgPSAxOwoKCWZvcmVhY2ggKCRxdWVzdGlvbnMgYXMgJHF1ZXN0aW9uKSB7CgkJZWNobyAiXG57JG51bWJlcn0uICI7CgkJZWNobyAkcXVlc3Rpb24tPmdldEFzU3RyaW5nKCk7CgoJCSRudW1iZXIgKys7Cgl9Cgp9CgovKiDQpNGD0L3QutGG0LjRjyDQv9C+0LvRg9GH0LDQtdGCINC80LDRgdGB0LjQstGLINCy0L7Qv9GA0L7RgdC+0LIg0Lgg0L7RgtCy0LXRgtC+0LIuINCf0YDQvtCy0LXRgNGP0LXRgiDQvtGC0LLQtdGC0YssIArRgdGH0LjRgtCw0LXRgiDRh9C40YHQu9C+INCx0LDQu9C70L7QsiDQuCDQv9C10YfQsNGC0LDQtdGCINCy0L7Qv9GA0L7RgdGLINC90LAg0LrQvtGC0L7RgNGL0LUg0LHRi9C7INC00LDQvSDQvdC10L/RgNCw0LLQuNC70YzQvdGL0Lkg0L7RgtCy0LXRgi4gKi8KCmZ1bmN0aW9uIGNoZWNrQW5zd2VycygkcXVlc3Rpb25zLCAkYW5zd2VycykKewogICAgaWYgKGNvdW50KCRxdWVzdGlvbnMpICE9IGNvdW50KCRhbnN3ZXJzKSkgewogICAgICAgIGRpZSgi0KfQuNGB0LvQviDQvtGC0LLQtdGC0L7QsiDQuCDQstC+0L/RgNC+0YHQvtCyINC90LUg0YHQvtCy0L/QsNC00LDQtdGCXG4iKTsKICAgIH0KCiAgICAkcG9pbnRzVG90YWwgPSAwOwogICAgJHBvaW50c01heCA9IDA7CiAgICAkY29ycmVjdEFuc3dlcnMgPSAwOwoKICAgICR0b3RhbFF1ZXN0aW9ucyA9IGNvdW50KCRxdWVzdGlvbnMpOwoKICAgIGZvciAoJGkgPSAwOyAkaSA8IGNvdW50KCRxdWVzdGlvbnMpOyAkaSsrKSB7CgogICAgICAgICRxdWVzdGlvbiA9ICRxdWVzdGlvbnNbJGldOwogICAgICAgICRhbnN3ZXIgPSAkYW5zd2Vyc1skaV07CgogICAgICAgIGxpc3QoJGlzQ29ycmVjdCwgJGlzQWxtb3N0Q29ycmVjdCkgPSAkcXVlc3Rpb24tPmNoZWNrQW5zd2VyKCRhbnN3ZXIpOwogICAgICAgICRwb2ludHMgPSAkcXVlc3Rpb24tPmdldFBvaW50cygpOwoKICAgICAgICAkcG9pbnRzTWF4ICs9ICRwb2ludHM7CgogICAgICAgIGlmICgkaXNDb3JyZWN0KSB7CgogICAgICAgICAgICAkY29ycmVjdEFuc3dlcnMgKys7CiAgICAgICAgICAgICRwb2ludHNUb3RhbCArPSAkcG9pbnRzOwoKICAgICAgICB9IGVsc2VpZiAoJGlzQWxtb3N0Q29ycmVjdCkgewoKICAgICAgICAJJGNvcnJlY3RBbnN3ZXJzICsrOwogICAgICAgICAgICAkcG9pbnRzVG90YWwgKz0gJHBvaW50cyAvIDI7CgogICAgICAgIH0gZWxzZSB7CgogICAgICAgICAgICAkbnVtYmVyID0gJGkgKyAxOwogICAgICAgICAgICBlY2hvICJcbtCd0LXQv9GA0LDQstC40LvRjNC90YvQuSDQvtGC0LLQtdGCINC90LAg0LLQvtC/0YDQvtGBIOKElnskbnVtYmVyfSAoeyRxdWVzdGlvbi0+Z2V0UXVlc3Rpb25UZXh0KCl9KVxuIjsKCQkJZWNobyAiXG7Qn9C+0LTRgdC60LDQt9C60LA6IHskcXVlc3Rpb24tPmdldFF1ZXN0aW9uSGludCgpfVxuIjsKCiAgICAgICAgfQoKICAgIH0KCiAgICBlY2hvICJcbtCf0YDQsNCy0LjQu9GM0L3Ri9GFINC+0YLQstC10YLQvtCyOiB7JGNvcnJlY3RBbnN3ZXJzfSDQuNC3IHskdG90YWxRdWVzdGlvbnN9LCDQsdCw0LvQu9C+0LIg0L3QsNCx0YDQsNC90L46ICRwb2ludHNUb3RhbCDQuNC3ICRwb2ludHNNYXhcbiI7Cn0KCiRxdWVzdGlvbnMgPSBjcmVhdGVRdWVzdGlvbnMoKTsKcHJpbnRRdWVzdGlvbnMoJHF1ZXN0aW9ucyk7CmNoZWNrQW5zd2VycygkcXVlc3Rpb25zLCBhcnJheSgnYicsICdkJywgJ2InLCAyOTk3OTIsIDMuMTQ0NDQsIDE5NDQpKTs=