<?php
abstract class Animal
{
protected $x;
protected $y;
protected $field;
protected $excludedAnimals = ["Mouse", "Cat", "Dog"];
public function __construct(Field $field)
{
$this->field = $field;
}
public function setX($x)
{
$this->x = $x;
}
public function setY($y)
{
$this->y = $y;
}
public function getX()
{
return $this->x;
}
public function getY()
{
return $this->y;
}
protected function findAvailableSteps
(array $offsets) {
$adjacentSteps = array_filter($offsets, [$this->field, "positionExists"]); $availableSteps = $this->field->findOpenSteps($adjacentSteps,
$this->excludedAnimals);
$availableSteps[] = [$this->x, $this->y];
return $availableSteps;
}
public function makeStep()
{
$availableSteps = $this->findAvailableSteps($this->findOffsets($this->x,
$this->y));
$estimatedSteps = [];
foreach($availableSteps as $step) {
$estimatedSteps[] = $this->estimateStep($step);
}
$prices = [];
foreach ($estimatedSteps as $step) {
$prices[] = $step["price"];
}
$bestPrice = max($prices); $bestStep = [];
foreach ($estimatedSteps as $step) {
if ($step["price"] === $bestPrice) {
$bestStep = $step;
break;
}
}
$this->x = $bestStep["x"];
$this->y = $bestStep["y"];
}
abstract public function getLabel();
abstract protected function findOffsets($x, $y);
abstract protected function estimateStep($step);
}
class Mouse extends Animal
{
private $label = "M";
public function getLabel()
{
return $this->label;
}
public function isProtected()
{
$currentPos = [$this->x, $this->y];
$adjacentMouses = $this->field->getVisibleAnimals("Mouse",
$currentPos,
3);
if (count($adjacentMouses) >= 2) { return true;
}
return false;
}
protected function findOffsets($x, $y)
{
$offsets = [
[$x - 1, $y],
[$x, $y + 1],
[$x + 1, $y],
[$x, $y - 1],
];
return $offsets;
}
protected function estimateStep($step)
{
$visibilityDiametr = 9;
$price = 500;
$estimatedStep = [];
$visibleCats = $this->field->getVisibleAnimals("Cat", $step, $visibilityDiametr);
if ($visibleCats) {
$nearestCat = $this->field->getNearestAnimal("Cat", $step);
$horizontalDiff = abs($step[0] - $nearestCat->getX()); $verticalDiff = abs($step[1] - $nearestCat->getY()); $price += ($horizontalDiff + $verticalDiff) * 100;
count($visibleCats) * 3 < 60 ?
$price -= count($visibleCats) * 3 : $price; }
$stepOffsets = $this->findOffsets($step[0], $step[1]);
$nextAvailableSteps = $this->findAvailableSteps($stepOffsets);
$price += count($nextAvailableSteps) * 10; $estimatedStep["x"] = $step[0];
$estimatedStep["y"] = $step[1];
$estimatedStep["price"] = $price;
return $estimatedStep;
}
}
class Cat extends Animal
{
private $label = "K";
private $stepsCounter = 1;
protected $excludedAnimals = ["Cat", "Dog"];
public function getLabel()
{
return $this->label;
}
protected function findOffsets($x, $y)
{
$offsets = [
[$x - 1, $y],
[$x - 1, $y + 1],
[$x, $y + 1],
[$x + 1, $y + 1],
[$x + 1, $y],
[$x + 1, $y - 1],
[$x, $y - 1],
[$x - 1, $y - 1],
];
return $offsets;
}
protected function findAvailableSteps
(array $offsets) {
$result = [];
$availableSteps = parent::findAvailableSteps($offsets);
foreach ($availableSteps as $step) {
if (!$this->field->positionIntersectsDogs($step)) {
$result[] = $step;
}
}
return $result;
}
protected function estimateStep($step)
{
$estimatedStep = [];
$price = 500;
$nearestMouse = $this->field->getNearestAnimal("Mouse", $step);
if ($nearestMouse) {
if ($nearestMouse->isProtected()) {
$price = -1000;
} else {
$horizontalDiff = abs($step[0] - $nearestMouse->getX()); $verticalDiff = abs($step[1] - $nearestMouse->getY()); $price -= ($horizontalDiff + $verticalDiff) * 10;
}
}
$estimatedStep["x"] = $step[0];
$estimatedStep["y"] = $step[1];
$estimatedStep["price"] = $price;
return $estimatedStep;
}
public function makeStep()
{
if ($this->label === "@") {
$this->stepsCounter = 0;
$this->label = "K";
} else {
parent::makeStep();
$this->stepsCounter++;
$mouses = $this->field->getAnimalsByType("Mouse");
foreach ($mouses as $m) {
if ($m->getX() === $this->x && $m->getY() === $this->y) {
$this->field->removeAnimal($m);
$this->label = "@";
$this->stepsCounter = 0;
}
}
if ($this->stepsCounter === 8) {
$this->label = "@";
}
}
}
}
class Dog extends Animal
{
private $label = "C";
public function getLabel()
{
return $this->label;
}
protected function findOffsets($x, $y)
{
$offsets = [
[$x - 2, $y],
[$x - 2, $y + 2],
[$x, $y + 2],
[$x + 2, $y + 2],
[$x + 2, $y],
[$x + 2, $y - 2],
[$x, $y - 2],
[$x - 2, $y - 2]
];
return $offsets;
}
protected function estimateStep($step)
{
$estimatedStep = [];
$randomPrice = rand(1, 10000); $estimatedStep["x"] = $step[0];
$estimatedStep["y"] = $step[1];
$estimatedStep["price"] = $randomPrice;
return $estimatedStep;
}
public function getAdjacentSteps()
{
$offsets = [
[$this->x - 1, $this->y],
[$this->x - 1, $this->y + 1],
[$this->x, $this->y + 1],
[$this->x + 1, $this->y + 1],
[$this->x + 1, $this->y],
[$this->x + 1, $this->y - 1],
[$this->x, $this->y - 1],
[$this->x - 1, $this->y - 1],
];
return array_filter($offsets, [$this->field, "positionExists"]); }
}
class Field
{
private $size;
private $animals;
public function __construct($size)
{
$this->size = $size;
}
public function getSize()
{
return $this->size;
}
public function getAnimals()
{
return $this->animals;
}
public function addAnimal(Animal $animal)
{
$this->animals[] = $animal;
}
public function removeAnimal(Animal $animal) {
unset($this->animals[$key]); }
public function getAnimalsByType($type)
{
$func = function($animal) use ($type) {
return $animal;
}
};
}
public function drawSchema()
{
$schema = [];
for ($i = 0; $i <= $this->size; $i++) {
$schema[] = $line;
}
foreach ($this->animals as $animal) {
$schema[$animal->getX()][$animal->getY()] = $animal->getLabel() . " ";
}
return $schema;
}
public function positionExists($pos)
{
$x = $pos[0];
$y = $pos[1];
$haystack = range(0, $this->size); return true;
}
return false;
}
public function getVisibleAnimals($type, $pos, $diametr)
{
$chosenAnimals = $this->getAnimalsByType($type);
$visibleAnimals = [];
foreach ($chosenAnimals as $animal) {
if (abs($pos[0] - $animal->getX()) <= floor($diametr / 2) && abs($pos[1] - $animal->getY()) <= floor($diametr / 2)) { $visibleAnimals[] = $animal;
}
}
return $visibleAnimals;
}
public function getNearestAnimal($type, $pos)
{
$chosenAnimals = $this->getAnimalsByType($type);
$animals = [];
foreach ($chosenAnimals as $animal) {
$posDiff = abs($pos[0] - $animal->getX()) + abs($pos[1] - $animal->getY()); $animals[$posDiff] = $animal;
}
if ($animals) {
return $animals[$minPosDiff];
}
return null;
}
public function printSchema()
{
$schema = $this->drawSchema();
for ($i = $this->size; $i >= 0; $i--) {
for ($j = 0; $j <= $this->size; $j++) {
echo $schema[$j][$i];
}
echo "\n";
}
}
public function positionIsBusy($pos)
{
foreach ($this->animals as $a) {
if ($a->getX() === $pos[0] && $a->getY() === $pos[1]) {
}
}
return null;
}
public function positionIntersectsDogs($step)
{
$dogs = $this->getAnimalsByType("Dog");
$dogsAdjPositions = [];
foreach ($dogs as $d) {
$d->getAdjacentSteps());
}
foreach ($dogsAdjPositions as $pos) {
if ($pos[0] === $step[0] && $pos[1] === $step[1]) {
return true;
}
}
return false;
}
public function findOpenSteps
(array $steps, array $animalTypes) {
$openSteps = [];
foreach ($steps as $step) {
if (!in_array($this->positionIsBusy($step), $animalTypes)) { $openSteps[] = $step;
}
}
return $openSteps;
}
}
class Game
{
private $numMouses;
private $numCats;
private $numDogs;
private $numSteps;
private $field;
private $stepNumber = 0;
public function __construct($numMouses, $numCats, $numDogs, $fieldSize, $numSteps)
{
$this->numMouses = $numMouses;
$this->numCats = $numCats;
$this->numDogs = $numDogs;
$this->numSteps = $numSteps;
$this->field = new Field($fieldSize);
}
private function createAnimals($limit, $animalType)
{
for ($i = 0; $i < $limit; $i++) {
$animal = new $animalType($this->field);
$this->field->addAnimal($animal);
}
}
private function setAnimalsPositions()
{
$unavailableX = [];
$unavailableY = [];
foreach ($this->field->getAnimals() as $animal) {
do {
$x = rand(1, $this->field->getSize()); $y = rand(1, $this->field->getSize()); $animal->setX($x);
$animal->setY($y);
} while (in_array($x, $unavailableX, true && $unavailableX[] = $animal->getX();
$unavailableY[] = $animal->getY();
}
}
private function makeReport()
{
$info = "Ход: " . $this->stepNumber .
"\tМышек: " . count($this->field->getAnimalsByType("Mouse")) . "\tКошек: " . count($this->field->getAnimalsByType("Cat")) . "\tСобак: " . count($this->field->getAnimalsByType("Dog")); return $info;
}
private function animalsMakeStep($animalClass)
{
foreach ($this->field->getAnimals() as $animal) {
$animal->makeStep();
}
}
}
public function start()
{
$this->createAnimals($this->numMouses, "Mouse");
$this->createAnimals($this->numCats, "Cat");
$this->createAnimals($this->numDogs, "Dog");
$this->setAnimalsPositions();
$this->stepNumber++;
echo $this->makeReport() . "\n";
$this->field->printSchema();
for ($i = 1; $i < $this->numSteps; $i++) {
$this->animalsMakeStep("Mouse");
$this->animalsMakeStep("Cat");
$this->animalsMakeStep("Dog");
$this->stepNumber++;
echo $this->makeReport() . "\n";
$this->field->printSchema();
if (count($this->field->getAnimalsByType("Mouse")) === 0) { break;
}
}
}
}
$game = new Game(4, 2, 1, 15, 30);
$game->start();
PD9waHAKCmVycm9yX3JlcG9ydGluZygtMSk7Cm1iX2ludGVybmFsX2VuY29kaW5nKCJ1dGYtOCIpOwoKYWJzdHJhY3QgY2xhc3MgQW5pbWFsCnsKICAgIHByb3RlY3RlZCAkeDsKICAgIHByb3RlY3RlZCAkeTsKICAgIHByb3RlY3RlZCAkZmllbGQ7CiAgICBwcm90ZWN0ZWQgJGV4Y2x1ZGVkQW5pbWFscyA9IFsiTW91c2UiLCAiQ2F0IiwgIkRvZyJdOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdChGaWVsZCAkZmllbGQpIAogICAgewogICAgICAgICR0aGlzLT5maWVsZCA9ICRmaWVsZDsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gc2V0WCgkeCkgCiAgICB7CiAgICAgICAgJHRoaXMtPnggPSAkeDsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gc2V0WSgkeSkgCiAgICB7CiAgICAgICAgJHRoaXMtPnkgPSAkeTsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0WCgpIAogICAgewogICAgICAgIHJldHVybiAkdGhpcy0+eDsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0WSgpIAogICAgewogICAgICAgIHJldHVybiAkdGhpcy0+eTsKICAgIH0KICAgICAgICAKICAgIHByb3RlY3RlZCBmdW5jdGlvbiBmaW5kQXZhaWxhYmxlU3RlcHMoYXJyYXkgJG9mZnNldHMpCiAgICB7CiAgICAgICAgJGFkamFjZW50U3RlcHMgPSBhcnJheV9maWx0ZXIoJG9mZnNldHMsIFskdGhpcy0+ZmllbGQsICJwb3NpdGlvbkV4aXN0cyJdKTsKICAgICAgICAkYXZhaWxhYmxlU3RlcHMgPSAkdGhpcy0+ZmllbGQtPmZpbmRPcGVuU3RlcHMoJGFkamFjZW50U3RlcHMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+ZXhjbHVkZWRBbmltYWxzKTsgCiAgICAgICAgJGF2YWlsYWJsZVN0ZXBzW10gPSBbJHRoaXMtPngsICR0aGlzLT55XTsKICAgICAgICByZXR1cm4gJGF2YWlsYWJsZVN0ZXBzOwogICAgfQogICAgCiAgICBwdWJsaWMgZnVuY3Rpb24gbWFrZVN0ZXAoKSAKICAgIHsKICAgICAgICAkYXZhaWxhYmxlU3RlcHMgPSAkdGhpcy0+ZmluZEF2YWlsYWJsZVN0ZXBzKCR0aGlzLT5maW5kT2Zmc2V0cygkdGhpcy0+eCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy0+eSkpOwogICAgICAgICRlc3RpbWF0ZWRTdGVwcyA9IFtdOwogICAgICAgIGZvcmVhY2goJGF2YWlsYWJsZVN0ZXBzIGFzICRzdGVwKSB7CiAgICAgICAgICAgICRlc3RpbWF0ZWRTdGVwc1tdID0gJHRoaXMtPmVzdGltYXRlU3RlcCgkc3RlcCk7CiAgICAgICAgfQogICAgICAgICRwcmljZXMgPSBbXTsKICAgICAgICBmb3JlYWNoICgkZXN0aW1hdGVkU3RlcHMgYXMgJHN0ZXApIHsKICAgICAgICAgICAgJHByaWNlc1tdID0gJHN0ZXBbInByaWNlIl07CiAgICAgICAgfQogICAgICAgICRiZXN0UHJpY2UgPSBtYXgoJHByaWNlcyk7CiAgICAgICAgJGJlc3RTdGVwID0gW107CiAgICAgICAgZm9yZWFjaCAoJGVzdGltYXRlZFN0ZXBzIGFzICRzdGVwKSB7CiAgICAgICAgICAgIGlmICgkc3RlcFsicHJpY2UiXSA9PT0gJGJlc3RQcmljZSkgewogICAgICAgICAgICAgICAgJGJlc3RTdGVwID0gJHN0ZXA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAkdGhpcy0+eCA9ICRiZXN0U3RlcFsieCJdOwogICAgICAgICR0aGlzLT55ID0gJGJlc3RTdGVwWyJ5Il07CiAgICB9CiAgICAKICAgIGFic3RyYWN0IHB1YmxpYyBmdW5jdGlvbiBnZXRMYWJlbCgpOwogICAgYWJzdHJhY3QgcHJvdGVjdGVkIGZ1bmN0aW9uIGZpbmRPZmZzZXRzKCR4LCAkeSk7CiAgICBhYnN0cmFjdCBwcm90ZWN0ZWQgZnVuY3Rpb24gZXN0aW1hdGVTdGVwKCRzdGVwKTsKfQoKY2xhc3MgTW91c2UgZXh0ZW5kcyBBbmltYWwgCnsKICAgIHByaXZhdGUgJGxhYmVsID0gIk0iOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRMYWJlbCgpIAogICAgewogICAgICAgIHJldHVybiAkdGhpcy0+bGFiZWw7CiAgICB9CiAgICAKICAgIHB1YmxpYyBmdW5jdGlvbiBpc1Byb3RlY3RlZCgpCiAgICB7CiAgICAgICAgJGN1cnJlbnRQb3MgPSBbJHRoaXMtPngsICR0aGlzLT55XTsKICAgICAgICAkYWRqYWNlbnRNb3VzZXMgPSAkdGhpcy0+ZmllbGQtPmdldFZpc2libGVBbmltYWxzKCJNb3VzZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkY3VycmVudFBvcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMpOwogICAgICAgIGlmIChjb3VudCgkYWRqYWNlbnRNb3VzZXMpID49IDIpIHsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIAogICAgcHJvdGVjdGVkIGZ1bmN0aW9uIGZpbmRPZmZzZXRzKCR4LCAkeSkKICAgIHsKICAgICAgICAkb2Zmc2V0cyA9IFsKICAgICAgICAgICAgWyR4IC0gMSwgJHldLAogICAgICAgICAgICBbJHgsICR5ICsgMV0sCiAgICAgICAgICAgIFskeCArIDEsICR5XSwKICAgICAgICAgICAgWyR4LCAkeSAtIDFdLAogICAgICAgIF07ICAgICAgICAKICAgICAgICByZXR1cm4gJG9mZnNldHM7CiAgICB9CiAgICAKICAgIHByb3RlY3RlZCBmdW5jdGlvbiBlc3RpbWF0ZVN0ZXAoJHN0ZXApIAogICAgewogICAgICAgICR2aXNpYmlsaXR5RGlhbWV0ciA9IDk7CiAgICAgICAgJHByaWNlID0gNTAwOwogICAgICAgICRlc3RpbWF0ZWRTdGVwID0gW107CiAgICAgICAgJHZpc2libGVDYXRzID0gJHRoaXMtPmZpZWxkLT5nZXRWaXNpYmxlQW5pbWFscygiQ2F0IiwgJHN0ZXAsICR2aXNpYmlsaXR5RGlhbWV0cik7CiAgICAgICAgaWYgKCR2aXNpYmxlQ2F0cykgewogICAgICAgICAgICAkbmVhcmVzdENhdCA9ICR0aGlzLT5maWVsZC0+Z2V0TmVhcmVzdEFuaW1hbCgiQ2F0IiwgJHN0ZXApOwogICAgICAgICAgICAkaG9yaXpvbnRhbERpZmYgPSBhYnMoJHN0ZXBbMF0gLSAkbmVhcmVzdENhdC0+Z2V0WCgpKTsKICAgICAgICAgICAgJHZlcnRpY2FsRGlmZiA9IGFicygkc3RlcFsxXSAtICRuZWFyZXN0Q2F0LT5nZXRZKCkpOwogICAgICAgICAgICAkcHJpY2UgKz0gKCRob3Jpem9udGFsRGlmZiArICR2ZXJ0aWNhbERpZmYpICogMTAwOwogICAgICAgICAgICBjb3VudCgkdmlzaWJsZUNhdHMpICogMyA8IDYwID8gJHByaWNlIC09IGNvdW50KCR2aXNpYmxlQ2F0cykgKiAzIDogJHByaWNlOwogICAgICAgIH0KICAgICAgICAkc3RlcE9mZnNldHMgPSAkdGhpcy0+ZmluZE9mZnNldHMoJHN0ZXBbMF0sICRzdGVwWzFdKTsKICAgICAgICAkbmV4dEF2YWlsYWJsZVN0ZXBzID0gJHRoaXMtPmZpbmRBdmFpbGFibGVTdGVwcygkc3RlcE9mZnNldHMpOwogICAgICAgICRwcmljZSArPSBjb3VudCgkbmV4dEF2YWlsYWJsZVN0ZXBzKSAqIDEwOwogICAgICAgICRlc3RpbWF0ZWRTdGVwWyJ4Il0gPSAkc3RlcFswXTsKICAgICAgICAkZXN0aW1hdGVkU3RlcFsieSJdID0gJHN0ZXBbMV07CiAgICAgICAgJGVzdGltYXRlZFN0ZXBbInByaWNlIl0gPSAkcHJpY2U7CiAgICAgICAgcmV0dXJuICRlc3RpbWF0ZWRTdGVwOwogICAgfQp9CgpjbGFzcyBDYXQgZXh0ZW5kcyBBbmltYWwgCnsKICAgIHByaXZhdGUgJGxhYmVsID0gIksiOwogICAgcHJpdmF0ZSAkc3RlcHNDb3VudGVyID0gMTsKICAgIHByb3RlY3RlZCAkZXhjbHVkZWRBbmltYWxzID0gWyJDYXQiLCAiRG9nIl07CgogICAgcHVibGljIGZ1bmN0aW9uIGdldExhYmVsKCkgCiAgICB7CiAgICAgICAgcmV0dXJuICR0aGlzLT5sYWJlbDsKICAgIH0KCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZmluZE9mZnNldHMoJHgsICR5KQogICAgewogICAgICAgICRvZmZzZXRzID0gWwogICAgICAgICAgICBbJHggLSAxLCAkeV0sCiAgICAgICAgICAgIFskeCAtIDEsICR5ICsgMV0sCiAgICAgICAgICAgIFskeCwgJHkgKyAxXSwKICAgICAgICAgICAgWyR4ICsgMSwgJHkgKyAxXSwKICAgICAgICAgICAgWyR4ICsgMSwgJHldLAogICAgICAgICAgICBbJHggKyAxLCAkeSAtIDFdLAogICAgICAgICAgICBbJHgsICR5IC0gMV0sCiAgICAgICAgICAgIFskeCAtIDEsICR5IC0gMV0sCiAgICAgICAgXTsKICAgICAgICByZXR1cm4gJG9mZnNldHM7CiAgICB9CiAgICAKICAgIHByb3RlY3RlZCBmdW5jdGlvbiBmaW5kQXZhaWxhYmxlU3RlcHMoYXJyYXkgJG9mZnNldHMpCiAgICB7CiAgICAgICAgJHJlc3VsdCA9IFtdOwogICAgICAgICRhdmFpbGFibGVTdGVwcyA9IHBhcmVudDo6ZmluZEF2YWlsYWJsZVN0ZXBzKCRvZmZzZXRzKTsKICAgICAgICBmb3JlYWNoICgkYXZhaWxhYmxlU3RlcHMgYXMgJHN0ZXApIHsKICAgICAgICAgICAgaWYgKCEkdGhpcy0+ZmllbGQtPnBvc2l0aW9uSW50ZXJzZWN0c0RvZ3MoJHN0ZXApKSB7CiAgICAgICAgICAgICAgICAkcmVzdWx0W10gPSAkc3RlcDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gJHJlc3VsdDsKICAgIH0KICAgIAogICAgcHJvdGVjdGVkIGZ1bmN0aW9uIGVzdGltYXRlU3RlcCgkc3RlcCkgCiAgICB7CiAgICAgICAgJGVzdGltYXRlZFN0ZXAgPSBbXTsKICAgICAgICAkcHJpY2UgPSA1MDA7CiAgICAgICAgJG5lYXJlc3RNb3VzZSA9ICR0aGlzLT5maWVsZC0+Z2V0TmVhcmVzdEFuaW1hbCgiTW91c2UiLCAkc3RlcCk7CiAgICAgICAgaWYgKCRuZWFyZXN0TW91c2UpIHsKICAgICAgICAgICAgaWYgKCRuZWFyZXN0TW91c2UtPmlzUHJvdGVjdGVkKCkpIHsKICAgICAgICAgICAgICAgICRwcmljZSA9IC0xMDAwOyAgICAKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICRob3Jpem9udGFsRGlmZiA9IGFicygkc3RlcFswXSAtICRuZWFyZXN0TW91c2UtPmdldFgoKSk7CiAgICAgICAgICAgICAgICAkdmVydGljYWxEaWZmID0gYWJzKCRzdGVwWzFdIC0gJG5lYXJlc3RNb3VzZS0+Z2V0WSgpKTsKICAgICAgICAgICAgICAgICRwcmljZSAtPSAoJGhvcml6b250YWxEaWZmICsgJHZlcnRpY2FsRGlmZikgKiAxMDsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAkZXN0aW1hdGVkU3RlcFsieCJdID0gJHN0ZXBbMF07CiAgICAgICAgJGVzdGltYXRlZFN0ZXBbInkiXSA9ICRzdGVwWzFdOwogICAgICAgICRlc3RpbWF0ZWRTdGVwWyJwcmljZSJdID0gJHByaWNlOwogICAgICAgIHJldHVybiAkZXN0aW1hdGVkU3RlcDsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gbWFrZVN0ZXAoKSAKICAgIHsKICAgICAgICBpZiAoJHRoaXMtPmxhYmVsID09PSAiQCIpIHsKICAgICAgICAgICAgJHRoaXMtPnN0ZXBzQ291bnRlciA9IDA7CiAgICAgICAgICAgICR0aGlzLT5sYWJlbCA9ICJLIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwYXJlbnQ6Om1ha2VTdGVwKCk7CiAgICAgICAgICAgICR0aGlzLT5zdGVwc0NvdW50ZXIrKzsKICAgICAgICAgICAgJG1vdXNlcyA9ICR0aGlzLT5maWVsZC0+Z2V0QW5pbWFsc0J5VHlwZSgiTW91c2UiKTsKICAgICAgICAgICAgZm9yZWFjaCAoJG1vdXNlcyBhcyAkbSkgewogICAgICAgICAgICAgICAgaWYgKCRtLT5nZXRYKCkgPT09ICR0aGlzLT54ICYmICRtLT5nZXRZKCkgPT09ICR0aGlzLT55KSB7CiAgICAgICAgICAgICAgICAgICAgJHRoaXMtPmZpZWxkLT5yZW1vdmVBbmltYWwoJG0pOwogICAgICAgICAgICAgICAgICAgICR0aGlzLT5sYWJlbCA9ICJAIjsKICAgICAgICAgICAgICAgICAgICAkdGhpcy0+c3RlcHNDb3VudGVyID0gMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoJHRoaXMtPnN0ZXBzQ291bnRlciA9PT0gOCkgewogICAgICAgICAgICAgICAgJHRoaXMtPmxhYmVsID0gIkAiOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CgpjbGFzcyBEb2cgZXh0ZW5kcyBBbmltYWwgCnsKICAgIHByaXZhdGUgJGxhYmVsID0gIkMiOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRMYWJlbCgpIAogICAgewogICAgICAgIHJldHVybiAkdGhpcy0+bGFiZWw7CiAgICB9CgogICAgcHJvdGVjdGVkIGZ1bmN0aW9uIGZpbmRPZmZzZXRzKCR4LCAkeSkgCiAgICB7CiAgICAgICAgJG9mZnNldHMgPSBbCiAgICAgICAgICAgICAgICAgICAgWyR4IC0gMiwgJHldLAogICAgICAgICAgICAgICAgICAgIFskeCAtIDIsICR5ICsgMl0sCiAgICAgICAgICAgICAgICAgICAgWyR4LCAkeSArIDJdLAogICAgICAgICAgICAgICAgICAgIFskeCArIDIsICR5ICsgMl0sCiAgICAgICAgICAgICAgICAgICAgWyR4ICsgMiwgJHldLAogICAgICAgICAgICAgICAgICAgIFskeCArIDIsICR5IC0gMl0sCiAgICAgICAgICAgICAgICAgICAgWyR4LCAkeSAtIDJdLAogICAgICAgICAgICAgICAgICAgIFskeCAtIDIsICR5IC0gMl0KICAgICAgICAgICAgICAgIF07CiAgICAgICAgcmV0dXJuICRvZmZzZXRzOwogICAgfQogICAgCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZXN0aW1hdGVTdGVwKCRzdGVwKQogICAgewogICAgICAgICRlc3RpbWF0ZWRTdGVwID0gW107CiAgICAgICAgJHJhbmRvbVByaWNlID0gcmFuZCgxLCAxMDAwMCk7CiAgICAgICAgJGVzdGltYXRlZFN0ZXBbIngiXSA9ICRzdGVwWzBdOwogICAgICAgICRlc3RpbWF0ZWRTdGVwWyJ5Il0gPSAkc3RlcFsxXTsKICAgICAgICAkZXN0aW1hdGVkU3RlcFsicHJpY2UiXSA9ICRyYW5kb21QcmljZTsKICAgICAgICByZXR1cm4gJGVzdGltYXRlZFN0ZXA7CiAgICB9CiAgICAKICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRBZGphY2VudFN0ZXBzKCkKICAgIHsKICAgICAgICAkb2Zmc2V0cyA9IFsKICAgICAgICAgICAgWyR0aGlzLT54IC0gMSwgJHRoaXMtPnldLAogICAgICAgICAgICBbJHRoaXMtPnggLSAxLCAkdGhpcy0+eSArIDFdLAogICAgICAgICAgICBbJHRoaXMtPngsICR0aGlzLT55ICsgMV0sCiAgICAgICAgICAgIFskdGhpcy0+eCArIDEsICR0aGlzLT55ICsgMV0sCiAgICAgICAgICAgIFskdGhpcy0+eCArIDEsICR0aGlzLT55XSwKICAgICAgICAgICAgWyR0aGlzLT54ICsgMSwgJHRoaXMtPnkgLSAxXSwKICAgICAgICAgICAgWyR0aGlzLT54LCAkdGhpcy0+eSAtIDFdLAogICAgICAgICAgICBbJHRoaXMtPnggLSAxLCAkdGhpcy0+eSAtIDFdLAogICAgICAgIF07CiAgICAgICAgcmV0dXJuIGFycmF5X2ZpbHRlcigkb2Zmc2V0cywgWyR0aGlzLT5maWVsZCwgInBvc2l0aW9uRXhpc3RzIl0pOwogICAgfQp9CgpjbGFzcyBGaWVsZCAKewogICAgcHJpdmF0ZSAkc2l6ZTsKICAgIHByaXZhdGUgJGFuaW1hbHM7CgogICAgcHVibGljIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRzaXplKSAKICAgIHsKICAgICAgICAkdGhpcy0+c2l6ZSA9ICRzaXplOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRTaXplKCkgCiAgICB7CiAgICAgICAgcmV0dXJuICR0aGlzLT5zaXplOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRBbmltYWxzKCkgCiAgICB7CiAgICAgICAgcmV0dXJuICR0aGlzLT5hbmltYWxzOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBhZGRBbmltYWwoQW5pbWFsICRhbmltYWwpIAogICAgewogICAgICAgICR0aGlzLT5hbmltYWxzW10gPSAkYW5pbWFsOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiByZW1vdmVBbmltYWwoQW5pbWFsICRhbmltYWwpIHsKICAgICAgICAka2V5ID0gYXJyYXlfc2VhcmNoKCRhbmltYWwsICR0aGlzLT5hbmltYWxzLCB0cnVlKTsKICAgICAgICB1bnNldCgkdGhpcy0+YW5pbWFsc1ska2V5XSk7CiAgICB9CgogICAgcHVibGljIGZ1bmN0aW9uIGdldEFuaW1hbHNCeVR5cGUoJHR5cGUpIAogICAgewogICAgICAgICRmdW5jID0gZnVuY3Rpb24oJGFuaW1hbCkgdXNlICgkdHlwZSkgewogICAgICAgICAgICBpZiAoZ2V0X2NsYXNzKCRhbmltYWwpID09PSAkdHlwZSkgewogICAgICAgICAgICAgICAgcmV0dXJuICRhbmltYWw7CiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHJldHVybiBhcnJheV9maWx0ZXIoJHRoaXMtPmFuaW1hbHMsICRmdW5jKTsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gZHJhd1NjaGVtYSgpIAogICAgewogICAgICAgICRzY2hlbWEgPSBbXTsKICAgICAgICBmb3IgKCRpID0gMDsgJGkgPD0gJHRoaXMtPnNpemU7ICRpKyspIHsKICAgICAgICAgICAgJGxpbmUgPSBhcnJheV9maWxsKDAsICR0aGlzLT5zaXplICsgMSwgIi4gIik7CiAgICAgICAgICAgICRzY2hlbWFbXSA9ICRsaW5lOwogICAgICAgIH0KICAgICAgICBmb3JlYWNoICgkdGhpcy0+YW5pbWFscyBhcyAkYW5pbWFsKSB7CiAgICAgICAgICAgICRzY2hlbWFbJGFuaW1hbC0+Z2V0WCgpXVskYW5pbWFsLT5nZXRZKCldID0gJGFuaW1hbC0+Z2V0TGFiZWwoKSAuICIgIjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuICRzY2hlbWE7CiAgICB9CgogICAgcHVibGljIGZ1bmN0aW9uIHBvc2l0aW9uRXhpc3RzKCRwb3MpCiAgICB7CiAgICAgICAgJHggPSAkcG9zWzBdOwogICAgICAgICR5ID0gJHBvc1sxXTsKICAgICAgICAkaGF5c3RhY2sgPSByYW5nZSgwLCAkdGhpcy0+c2l6ZSk7CiAgICAgICAgaWYgKGluX2FycmF5KCR4LCAkaGF5c3RhY2spICYmIGluX2FycmF5KCR5LCAkaGF5c3RhY2spKSB7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgcHVibGljIGZ1bmN0aW9uIGdldFZpc2libGVBbmltYWxzKCR0eXBlLCAkcG9zLCAkZGlhbWV0cikgCiAgICB7CiAgICAgICAgJGNob3NlbkFuaW1hbHMgPSAkdGhpcy0+Z2V0QW5pbWFsc0J5VHlwZSgkdHlwZSk7CiAgICAgICAgJHZpc2libGVBbmltYWxzID0gW107CiAgICAgICAgZm9yZWFjaCAoJGNob3NlbkFuaW1hbHMgYXMgJGFuaW1hbCkgewogICAgICAgICAgICBpZiAoYWJzKCRwb3NbMF0gLSAkYW5pbWFsLT5nZXRYKCkpIDw9IGZsb29yKCRkaWFtZXRyIC8gMikgJiYKICAgICAgICAgICAgICAgIGFicygkcG9zWzFdIC0gJGFuaW1hbC0+Z2V0WSgpKSA8PSBmbG9vcigkZGlhbWV0ciAvIDIpKSB7CiAgICAgICAgICAgICAgICAkdmlzaWJsZUFuaW1hbHNbXSA9ICRhbmltYWw7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuICR2aXNpYmxlQW5pbWFsczsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0TmVhcmVzdEFuaW1hbCgkdHlwZSwgJHBvcykgCiAgICB7CiAgICAgICAgJGNob3NlbkFuaW1hbHMgPSAkdGhpcy0+Z2V0QW5pbWFsc0J5VHlwZSgkdHlwZSk7CiAgICAgICAgJGFuaW1hbHMgPSBbXTsKICAgICAgICBmb3JlYWNoICgkY2hvc2VuQW5pbWFscyBhcyAkYW5pbWFsKSB7CiAgICAgICAgICAgICRwb3NEaWZmID0gYWJzKCRwb3NbMF0gLSAkYW5pbWFsLT5nZXRYKCkpICsKICAgICAgICAgICAgICAgICAgICAgICBhYnMoJHBvc1sxXSAtICRhbmltYWwtPmdldFkoKSk7CiAgICAgICAgICAgICRhbmltYWxzWyRwb3NEaWZmXSA9ICRhbmltYWw7CiAgICAgICAgfQogICAgICAgIGlmICgkYW5pbWFscykgewogICAgICAgICAgICAkbWluUG9zRGlmZiA9IG1pbihhcnJheV9rZXlzKCRhbmltYWxzKSk7CiAgICAgICAgICAgIHJldHVybiAkYW5pbWFsc1skbWluUG9zRGlmZl07ICAgICAgICAKICAgICAgICB9IAogICAgICAgIHJldHVybiBudWxsOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBwcmludFNjaGVtYSgpIAogICAgewogICAgICAgICRzY2hlbWEgPSAkdGhpcy0+ZHJhd1NjaGVtYSgpOwogICAgICAgIGZvciAoJGkgPSAkdGhpcy0+c2l6ZTsgJGkgPj0gMDsgJGktLSkgewogICAgICAgICAgICBmb3IgKCRqID0gMDsgJGogPD0gJHRoaXMtPnNpemU7ICRqKyspIHsKICAgICAgICAgICAgICAgIGVjaG8gJHNjaGVtYVskal1bJGldOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVjaG8gIlxuIjsKICAgICAgICB9CiAgICB9CiAgICAKICAgIHB1YmxpYyBmdW5jdGlvbiBwb3NpdGlvbklzQnVzeSgkcG9zKQogICAgewogICAgICAgIGZvcmVhY2ggKCR0aGlzLT5hbmltYWxzIGFzICRhKSB7CiAgICAgICAgICAgIGlmICgkYS0+Z2V0WCgpID09PSAkcG9zWzBdICYmICRhLT5nZXRZKCkgPT09ICRwb3NbMV0pIHsKICAgICAgICAgICAgICAgIHJldHVybiBnZXRfY2xhc3MoJGEpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgCiAgICBwdWJsaWMgZnVuY3Rpb24gcG9zaXRpb25JbnRlcnNlY3RzRG9ncygkc3RlcCkKICAgIHsKICAgICAgICAkZG9ncyA9ICR0aGlzLT5nZXRBbmltYWxzQnlUeXBlKCJEb2ciKTsKICAgICAgICAkZG9nc0FkalBvc2l0aW9ucyA9IFtdOwogICAgICAgIGZvcmVhY2ggKCRkb2dzIGFzICRkKSB7CiAgICAgICAgICAgICRkb2dzQWRqUG9zaXRpb25zID0gYXJyYXlfbWVyZ2UoJGRvZ3NBZGpQb3NpdGlvbnMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRkLT5nZXRBZGphY2VudFN0ZXBzKCkpOwogICAgICAgIH0KICAgICAgICBmb3JlYWNoICgkZG9nc0FkalBvc2l0aW9ucyBhcyAkcG9zKSB7CiAgICAgICAgICAgIGlmICgkcG9zWzBdID09PSAkc3RlcFswXSAmJiAkcG9zWzFdID09PSAkc3RlcFsxXSkgewogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgCiAgICBwdWJsaWMgZnVuY3Rpb24gZmluZE9wZW5TdGVwcyhhcnJheSAkc3RlcHMsIGFycmF5ICRhbmltYWxUeXBlcykKICAgIHsKICAgICAgICAkb3BlblN0ZXBzID0gW107CiAgICAgICAgZm9yZWFjaCAoJHN0ZXBzIGFzICRzdGVwKSB7CiAgICAgICAgICAgIGlmICghaW5fYXJyYXkoJHRoaXMtPnBvc2l0aW9uSXNCdXN5KCRzdGVwKSwgJGFuaW1hbFR5cGVzKSkgewogICAgICAgICAgICAgICAgJG9wZW5TdGVwc1tdID0gJHN0ZXA7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuICRvcGVuU3RlcHM7ICAKICAgIH0gICAgCn0KCmNsYXNzIEdhbWUgCnsKICAgIHByaXZhdGUgJG51bU1vdXNlczsKICAgIHByaXZhdGUgJG51bUNhdHM7CiAgICBwcml2YXRlICRudW1Eb2dzOwogICAgcHJpdmF0ZSAkbnVtU3RlcHM7CiAgICBwcml2YXRlICRmaWVsZDsKICAgIHByaXZhdGUgJHN0ZXBOdW1iZXIgPSAwOwoKICAgIHB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdCgkbnVtTW91c2VzLCAkbnVtQ2F0cywgJG51bURvZ3MsICRmaWVsZFNpemUsICRudW1TdGVwcykgCiAgICB7CiAgICAgICAgJHRoaXMtPm51bU1vdXNlcyA9ICRudW1Nb3VzZXM7CiAgICAgICAgJHRoaXMtPm51bUNhdHMgPSAkbnVtQ2F0czsKICAgICAgICAkdGhpcy0+bnVtRG9ncyA9ICRudW1Eb2dzOwogICAgICAgICR0aGlzLT5udW1TdGVwcyA9ICRudW1TdGVwczsKICAgICAgICAkdGhpcy0+ZmllbGQgPSBuZXcgRmllbGQoJGZpZWxkU2l6ZSk7CiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBjcmVhdGVBbmltYWxzKCRsaW1pdCwgJGFuaW1hbFR5cGUpIAogICAgewogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8ICRsaW1pdDsgJGkrKykgewogICAgICAgICAgICAkYW5pbWFsID0gbmV3ICRhbmltYWxUeXBlKCR0aGlzLT5maWVsZCk7CiAgICAgICAgICAgICR0aGlzLT5maWVsZC0+YWRkQW5pbWFsKCRhbmltYWwpOwogICAgICAgIH0KICAgIH0KCiAgICBwcml2YXRlIGZ1bmN0aW9uIHNldEFuaW1hbHNQb3NpdGlvbnMoKSAKICAgIHsKICAgICAgICAkdW5hdmFpbGFibGVYID0gW107CiAgICAgICAgJHVuYXZhaWxhYmxlWSA9IFtdOwogICAgICAgIGZvcmVhY2ggKCR0aGlzLT5maWVsZC0+Z2V0QW5pbWFscygpIGFzICRhbmltYWwpIHsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgJHggPSByYW5kKDEsICR0aGlzLT5maWVsZC0+Z2V0U2l6ZSgpKTsKICAgICAgICAgICAgICAgICR5ID0gcmFuZCgxLCAkdGhpcy0+ZmllbGQtPmdldFNpemUoKSk7CiAgICAgICAgICAgICAgICAkYW5pbWFsLT5zZXRYKCR4KTsKICAgICAgICAgICAgICAgICRhbmltYWwtPnNldFkoJHkpOwogICAgICAgICAgICB9IHdoaWxlIChpbl9hcnJheSgkeCwgJHVuYXZhaWxhYmxlWCwgdHJ1ZSAmJgogICAgICAgICAgICAgICAgICAgIGluX2FycmF5KCR5LCAkdW5hdmFpbGFibGVZLCB0cnVlKSkpOwogICAgICAgICAgICAkdW5hdmFpbGFibGVYW10gPSAkYW5pbWFsLT5nZXRYKCk7CiAgICAgICAgICAgICR1bmF2YWlsYWJsZVlbXSA9ICRhbmltYWwtPmdldFkoKTsKICAgICAgICB9CiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBtYWtlUmVwb3J0KCkgCiAgICB7CiAgICAgICAgJGluZm8gPSAi0KXQvtC0OiAiIC4gJHRoaXMtPnN0ZXBOdW1iZXIgLgogICAgICAgICAgICAgICAgIlx00JzRi9GI0LXQujogIiAuIGNvdW50KCR0aGlzLT5maWVsZC0+Z2V0QW5pbWFsc0J5VHlwZSgiTW91c2UiKSkgLgogICAgICAgICAgICAgICAgIlx00JrQvtGI0LXQujogIiAuIGNvdW50KCR0aGlzLT5maWVsZC0+Z2V0QW5pbWFsc0J5VHlwZSgiQ2F0IikpIC4KICAgICAgICAgICAgICAgICJcdNCh0L7QsdCw0Lo6ICIgLiBjb3VudCgkdGhpcy0+ZmllbGQtPmdldEFuaW1hbHNCeVR5cGUoIkRvZyIpKTsKICAgICAgICByZXR1cm4gJGluZm87CiAgICB9CgogICAgcHJpdmF0ZSBmdW5jdGlvbiBhbmltYWxzTWFrZVN0ZXAoJGFuaW1hbENsYXNzKSAKICAgIHsKICAgICAgICBmb3JlYWNoICgkdGhpcy0+ZmllbGQtPmdldEFuaW1hbHMoKSBhcyAkYW5pbWFsKSB7CiAgICAgICAgICAgIGlmIChnZXRfY2xhc3MoJGFuaW1hbCkgPT09ICRhbmltYWxDbGFzcykgewogICAgICAgICAgICAgICAgJGFuaW1hbC0+bWFrZVN0ZXAoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gc3RhcnQoKSAKICAgIHsKICAgICAgICAkdGhpcy0+Y3JlYXRlQW5pbWFscygkdGhpcy0+bnVtTW91c2VzLCAiTW91c2UiKTsKICAgICAgICAkdGhpcy0+Y3JlYXRlQW5pbWFscygkdGhpcy0+bnVtQ2F0cywgIkNhdCIpOwogICAgICAgICR0aGlzLT5jcmVhdGVBbmltYWxzKCR0aGlzLT5udW1Eb2dzLCAiRG9nIik7CiAgICAgICAgJHRoaXMtPnNldEFuaW1hbHNQb3NpdGlvbnMoKTsKICAgICAgICAkdGhpcy0+c3RlcE51bWJlcisrOwogICAgICAgIGVjaG8gJHRoaXMtPm1ha2VSZXBvcnQoKSAuICJcbiI7CiAgICAgICAgJHRoaXMtPmZpZWxkLT5wcmludFNjaGVtYSgpOwogICAgICAgIGZvciAoJGkgPSAxOyAkaSA8ICR0aGlzLT5udW1TdGVwczsgJGkrKykgewogICAgICAgICAgICAkdGhpcy0+YW5pbWFsc01ha2VTdGVwKCJNb3VzZSIpOwogICAgICAgICAgICAkdGhpcy0+YW5pbWFsc01ha2VTdGVwKCJDYXQiKTsKICAgICAgICAgICAgJHRoaXMtPmFuaW1hbHNNYWtlU3RlcCgiRG9nIik7CiAgICAgICAgICAgICR0aGlzLT5zdGVwTnVtYmVyKys7CiAgICAgICAgICAgIGVjaG8gJHRoaXMtPm1ha2VSZXBvcnQoKSAuICJcbiI7CiAgICAgICAgICAgICR0aGlzLT5maWVsZC0+cHJpbnRTY2hlbWEoKTsKICAgICAgICAgICAgaWYgKGNvdW50KCR0aGlzLT5maWVsZC0+Z2V0QW5pbWFsc0J5VHlwZSgiTW91c2UiKSkgPT09IDApIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CgoKJGdhbWUgPSBuZXcgR2FtZSg0LCAyLCAxLCAxNSwgMzApOwokZ2FtZS0+c3RhcnQoKTsK