<?php
class PrettyPrinter
{
private $head = [
"col0" => "№",
"col1" => "департамент",
"col2" => "Σрабов",
"col3" => "Σтугриков",
"col4" => "Σкофе",
"col5" => "Σстраниц",
"col6" => "тугриков/страниц"
];
private $foot = [
"col0" => " ",
"col1" => "Итого",
"col2" => NULL,
"col3" => NULL,
"col4" => NULL,
"col5" => NULL,
"col6" => NULL
];
private $trail = [];
private $padder;
private $prettyData = [];
private $printableResult;
public function __construct
(array $departments) {
$this->setPadder();
$this->setHeadTrials();
$inputArr= [];
foreach($departments as $department) {
$input["col1"] = $department->getDepName();
$input["col2"] = $department->getEmployeesNum();
$input["col3"] = $department->getTotalSalary();
$input["col4"] = $department->getTotalCoffee();
$input["col5"] = $department->getTotalPages();
$input["col6"] = number_format($department->getSalaryPagesRatio(), 3);
}
for($i = 0; $i < count($inputArr); $i++) { $inputArr[$i] = array_merge(["№" => $enum[$i]], $inputArr[$i]); $this->fillPrettyData($inputArr[$i]);
}
$this->setPrintableHeader();
$this->initFooter($inputArr);
$this->setPrintableFoot();
foreach($this->prettyData as $row) {
$this->setPrintableResult($row);
}
}
private function setPrintableHeader()
{
$this->printableResult .= (string)($header);
$this->printableResult .= " ";
}
$this->printableResult .= ("\n" . str_repeat("-", $this->padder) . "\n"); }
private function setHeadTrials()
{
foreach($this->head as $col=>$str) {
}
}
private function setPadder()
{
$func = function($value) {
};
}
private function fillPrettyData
(array $arr) {
$func = function($value) {
};
$dataLens = [];
foreach($temp as $len1=>$len2) {
$len = abs($len1 - $len2); }
$dataLens);
}
private function setPrintableResult
(array $arr) {
foreach($arr as $data=>$padding) {
$res = (string)$data . (string)$padding;
$this->printableResult .= $res;
$this->printableResult .= " ";
}
$this->printableResult .= ("\n" . str_repeat("-", $this->padder) . "\n"); }
public function __toString()
{
return $this->printableResult;
}
private function initFooter
(array $arr) {
$allWorkers = 0;
$allCoffee = 0;
$allSalary = 0;
$allPages = 0;
$allAvg = [];
foreach($arr as $subarr) {
$allWorkers += $cur_vals[2];
$allSalary += $cur_vals[3];
$allCoffee += $cur_vals[4];
$allPages += $cur_vals[5];
}
$this->foot["col2"] = $allWorkers;
$this->foot["col3"] = $allSalary;
$this->foot["col4"] = $allCoffee;
$this->foot["col5"] = $allPages;
}
private function setPrintableFoot()
{
$this->fillPrettyData($this->foot);
}
}
abstract class Employee
{
private $salary;
private $rank;
private $coffeeAmt;
private $pages;
private $isBoss;
public function __construct($salary, $rank, $coffeeAmt, $pages, $boss=false)
{
$this->salary = $salary;
$this->rank = $rank;
$this->coffeeAmt = $coffeeAmt;
$this->pages = $pages;
$this->isBoss = $boss;
}
public function getSalary()
{
if ($this->rank === 1) {
$salary = $this->salary;
} elseif($this->rank === 2) {
$salary = $this->salary * 1.25;
} elseif($this->rank === 3) {
$salary = $this->salary * 1.5;
}
if($this->isBoss) {
$salary += $salary * 0.5;
}
return $salary;
}
public function getCoffee()
{
if($this->isBoss) {
return $this->coffeeAmt * 2;
}
return $this->coffeeAmt;
}
public function getPages()
{
if($this->isBoss) {
return 0;
}
return $this->pages;
}
public function isBoss()
{
return $this->isBoss;
}
public function getRank()
{
return $this->rank;
}
public function setRank($rank)
{
$this->rank = $rank;
}
public function setSalary($salary)
{
$this->salary = $salary;
}
public function setCoffee($amt)
{
$this->coffeeAmt = $amt;
}
public function setPages($amt)
{
$this->pages = $amt;
}
public function setBossStatus($status)
{
$this->isBoss = $status;
}
}
class Manager extends Employee
{
}
class Analyst extends Employee
{
}
class Engineer extends Employee
{
}
class Marketer extends Employee
{
}
class Department
{
private $employees = [];
private $depName;
public function __construct($depName)
{
$this->depName = $depName;
}
public function addEmployee(Employee $emp)
{
}
public function fireEmployee(Employee $emp)
{
if(in_array($emp, $this->employees, true)) { unset($this->employees[$key]); }
}
public function setNewBoss(Employee $emp)
{
foreach($this->employees as $employee) {
if($employee->isBoss()) {
$employee->setBossStatus(false);
}
}
if(in_array($emp, $this->employees, true)) { $emp->setBossStatus(true);
}
}
public function getTotalSalary()
{
$totalSalary = 0;
foreach($this->employees as $employee) {
$totalSalary += $employee->getSalary();
}
return $totalSalary;
}
public function getTotalPages()
{
$totalWorkDone = 0;
foreach($this->employees as $employee) {
$totalWorkDone += $employee->getPages();
}
return $totalWorkDone;
}
public function getTotalCoffee()
{
$totalCoffeeAmount = 0;
foreach($this->employees as $employee) {
$totalCoffeeAmount += $employee->getCoffee();
}
return $totalCoffeeAmount;
}
public function getEmployeesNum()
{
return count($this->employees); }
public function getSalaryPagesRatio()
{
if($this->getTotalPages() !== 0) {
return $this->getTotalSalary() / $this->getTotalPages();
}
exit("В этом департаменте одни бездельники!\n"); }
public function getDepName()
{
return $this->depName;
}
public function getEmployees()
{
return $this->employees;
}
public function __clone()
{
$clonedEmps = [];
foreach($this->employees as $emp) {
$clonedEmps[] = clone $emp;
}
$this->employees = $clonedEmps;
$this->totalSalary = 0;
$this->totalCoffeeAmount = 0;
$this->totalWorkDone = 0;
}
}
function createEmployee(Department $dep, $cls, $rank, $amt, $boss=false)
{
$empSalarys = ["Manager" => 500, "Marketer" => 400, "Analyst" => 800, "Engineer" => 200];
$empCoffee = ["Manager" => 20, "Marketer" => 15, "Analyst" => 50, "Engineer" => 5];
$empPages = ["Manager" => 200, "Marketer" => 150, "Analyst" => 5, "Engineer" => 50];
for($i = 0; $i < $amt; $i++) {
$emp = new $cls($empSalarys[$cls], $rank, $empCoffee[$cls], $empPages[$cls], $boss);
$dep->addEmployee($emp);
}
}
function cmpRanks(Employee $emp1, Employee $emp2)
{
if($emp1->getRank() === $emp2->getRank()) {
return 0;
}
return ($emp1->getRank() < $emp2->getRank()) ? -1 : 1;
}
function tryModel1(Department $dep)
{
$engineers = [];
foreach($dep->getEmployees() as $emp) {
if(get_class($emp) === "Engineer" && $emp->isBoss() !== true) { $engineers[] = $emp;
}
}
usort($engineers, "cmpRanks"); $firedEngineers = array_slice($engineers, 0, $fireAmt); foreach($firedEngineers as $engineer) {
$dep->fireEmployee($engineer);
}
}
function tryModel2(Department $dep)
{
$analysts = [];
foreach($dep->getEmployees() as $emp) {
$emp->setSalary(1100);
$emp->setCoffee(75);
$analysts[] = $emp;
}
}
if($analysts) {
usort($analysts, "cmpRanks"); foreach($dep->getEmployees() as $emp) {
if($emp->isBoss() && get_class($emp) !== "Analyst") { $dep->setNewBoss(end($analysts)); }
}
}
}
function tryModel3(Department $dep)
{
$firstRankMan = [];
$secondRankMan = [];
foreach($dep->getEmployees() as $emp) {
if(get_class($emp) === "Manager" && $emp->getRank() === 1 && $emp->isBoss() === false) { $firstRankMan[] = $emp;
} elseif(get_class($emp) === "Manager" && $emp->getRank() === 2 && $emp->isBoss() === false) { $secondRankMan[] = $emp;
}
}
foreach($firstRankLim as $manager) {
$manager->setRank(2);
}
foreach($secondRankLim as $manager) {
$manager->setRank(3);
}
}
$purchaseDep = new Department("закупок");
createEmployee($purchaseDep, "Manager", 1, 9);
createEmployee($purchaseDep, "Manager", 2, 3);
createEmployee($purchaseDep, "Manager", 3, 2);
createEmployee($purchaseDep, "Marketer", 1, 2);
createEmployee($purchaseDep, "Manager", 2, 1, true);
$salesDep = new Department("продаж");
createEmployee($salesDep, "Manager", 1, 12);
createEmployee($salesDep, "Marketer", 1, 6);
createEmployee($salesDep, "Analyst", 1, 3);
createEmployee($salesDep, "Analyst", 2, 2);
createEmployee($salesDep, "Marketer", 2, 1, true);
$adsDep = new Department("рекламы");
createEmployee($adsDep, "Marketer", 1, 15);
createEmployee($adsDep, "Marketer", 2, 10);
createEmployee($adsDep, "Manager", 1, 8);
createEmployee($adsDep, "Engineer", 1, 2);
createEmployee($adsDep, "Marketer", 3, 1, true);
$logisticsDep = new Department("логистики");
createEmployee($logisticsDep, "Manager", 1, 13);
createEmployee($logisticsDep, "Manager", 2, 5);
createEmployee($logisticsDep, "Engineer", 1, 5);
createEmployee($logisticsDep, "Manager", 1, 1, true);
$allDeps = [$purchaseDep, $salesDep, $adsDep, $logisticsDep];
function cloneDepartments
(array $departments) { $clonedDeps = [];
foreach($departments as $dep) {
$clonedDeps[] = clone $dep;
}
return $clonedDeps;
}
function tryCrisisModel
(array $clonedDeps, callable
$modelFunc, $description) {
$result = new PrettyPrinter($clonedDeps);
echo "\n\n";
echo "Применение атнкризисной модели: {$description}\n\n";
echo $result;
}
$baseData = new PrettyPrinter($allDeps);
$clonedDeps1 = cloneDepartments($allDeps);
$clonedDeps2 = cloneDepartments($allDeps);
$clonedDeps3 = cloneDepartments($allDeps);
echo "Начальные данные.\n\n";
echo $baseData;
tryCrisisModel($clonedDeps1, "tryModel1", "увольнение 40% инженеров");
tryCrisisModel($clonedDeps2, "tryModel2", "повышение условий труда аналитиков");
tryCrisisModel($clonedDeps3, "tryModel3", "повышение 1 и 2 рангов у 50% менеджеров");
?>
PD9waHAKCgptYl9pbnRlcm5hbF9lbmNvZGluZygidXRmLTgiKTsKZXJyb3JfcmVwb3J0aW5nKC0xKTsKCgpjbGFzcyBQcmV0dHlQcmludGVyCnsKCXByaXZhdGUgJGhlYWQgPSBbCgkJCQkJImNvbDAiID0+ICLihJYiLAoJCQkJCSJjb2wxIiA9PiAi0LTQtdC/0LDRgNGC0LDQvNC10L3RgiIsCgkJCQkJImNvbDIiID0+ICLOo9GA0LDQsdC+0LIiLAoJCQkJCSJjb2wzIiA9PiAizqPRgtGD0LPRgNC40LrQvtCyIiwKCQkJCQkiY29sNCIgPT4gIs6j0LrQvtGE0LUiLAoJCQkJCSJjb2w1IiA9PiAizqPRgdGC0YDQsNC90LjRhiIsCgkJCQkJImNvbDYiID0+ICLRgtGD0LPRgNC40LrQvtCyL9GB0YLRgNCw0L3QuNGGIgoJICAgICAgICAgICAgIF07Cglwcml2YXRlICRmb290ID0gWwoJCQkJCSJjb2wwIiA9PiAiICIsCgkJCQkJImNvbDEiID0+ICLQmNGC0L7Qs9C+IiwKCQkJCQkiY29sMiIgPT4gTlVMTCwKCQkJCQkiY29sMyIgPT4gTlVMTCwKCQkJCQkiY29sNCIgPT4gTlVMTCwKCQkJCQkiY29sNSIgPT4gTlVMTCwKCQkJCQkiY29sNiIgPT4gTlVMTAoJICAgICAgICAgICAgIF07CQkJIAoJcHJpdmF0ZSAkdHJhaWwgPSBbXTsKCXByaXZhdGUgJHBhZGRlcjsKCQoJcHJpdmF0ZSAkcHJldHR5RGF0YSA9IFtdOwoJcHJpdmF0ZSAkcHJpbnRhYmxlUmVzdWx0OwoJCglwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoYXJyYXkgJGRlcGFydG1lbnRzKSAKCXsKCSAgICAkdGhpcy0+c2V0UGFkZGVyKCk7CgkgICAgJHRoaXMtPnNldEhlYWRUcmlhbHMoKTsKCSAgICAkaW5wdXRBcnI9IFtdOwoJCWZvcmVhY2goJGRlcGFydG1lbnRzIGFzICRkZXBhcnRtZW50KSB7CgkJCSRpbnB1dFsiY29sMSJdID0gJGRlcGFydG1lbnQtPmdldERlcE5hbWUoKTsgCgkJCSRpbnB1dFsiY29sMiJdID0gJGRlcGFydG1lbnQtPmdldEVtcGxveWVlc051bSgpOwoJCQkkaW5wdXRbImNvbDMiXSA9ICRkZXBhcnRtZW50LT5nZXRUb3RhbFNhbGFyeSgpOwkKCQkJJGlucHV0WyJjb2w0Il0gPSAkZGVwYXJ0bWVudC0+Z2V0VG90YWxDb2ZmZWUoKTsKCQkJJGlucHV0WyJjb2w1Il0gPSAkZGVwYXJ0bWVudC0+Z2V0VG90YWxQYWdlcygpOwoJCQkkaW5wdXRbImNvbDYiXSA9IG51bWJlcl9mb3JtYXQoJGRlcGFydG1lbnQtPmdldFNhbGFyeVBhZ2VzUmF0aW8oKSwgMyk7CgkJCQoJCQlhcnJheV9wdXNoKCRpbnB1dEFyciwgJGlucHV0KTsKCSAgIAl9CiAgICAgICAgJGVudW0gPSByYW5nZSgxLCBjb3VudCgkaW5wdXRBcnIpKTsJCgkJZm9yKCRpID0gMDsgJGkgPCBjb3VudCgkaW5wdXRBcnIpOyAkaSsrKSB7CgkJICAgICRpbnB1dEFyclskaV0gPSBhcnJheV9tZXJnZShbIuKEliIgPT4gJGVudW1bJGldXSwgJGlucHV0QXJyWyRpXSk7CiAgICAgICAgICAgICR0aGlzLT5maWxsUHJldHR5RGF0YSgkaW5wdXRBcnJbJGldKTsKCQl9CgkJCgkJJHRoaXMtPnNldFByaW50YWJsZUhlYWRlcigpOwoJCSR0aGlzLT5pbml0Rm9vdGVyKCRpbnB1dEFycik7CgkJJHRoaXMtPnNldFByaW50YWJsZUZvb3QoKTsKCQlmb3JlYWNoKCR0aGlzLT5wcmV0dHlEYXRhIGFzICRyb3cpIHsKCQkgICAgJHRoaXMtPnNldFByaW50YWJsZVJlc3VsdCgkcm93KTsKCQl9Cgl9CgkKCXByaXZhdGUgZnVuY3Rpb24gc2V0UHJpbnRhYmxlSGVhZGVyKCkKCXsKCSAgICBmb3JlYWNoKGFycmF5X3ZhbHVlcygkdGhpcy0+aGVhZCkgYXMgJGhlYWRlcikgewoJICAgICAgICAkdGhpcy0+cHJpbnRhYmxlUmVzdWx0IC49IChzdHJpbmcpKCRoZWFkZXIpOwoJCQkkdGhpcy0+cHJpbnRhYmxlUmVzdWx0IC49ICIgIjsKCQl9CgkJJHRoaXMtPnByaW50YWJsZVJlc3VsdCAuPSAoIlxuIiAuIHN0cl9yZXBlYXQoIi0iLCAkdGhpcy0+cGFkZGVyKSAuICJcbiIpOwoJfQoJCglwcml2YXRlIGZ1bmN0aW9uIHNldEhlYWRUcmlhbHMoKQoJewoJICAgIGZvcmVhY2goJHRoaXMtPmhlYWQgYXMgJGNvbD0+JHN0cikgewoJCQkkdGhpcy0+dHJhaWxbJGNvbF0gPSBtYl9zdHJsZW4oJHN0cik7CgkJfQkJCQkJCQkgCgl9CgkKCXByaXZhdGUgZnVuY3Rpb24gc2V0UGFkZGVyKCkKCXsKCSAgICAkZnVuYyA9IGZ1bmN0aW9uKCR2YWx1ZSkgewoJCSAgICByZXR1cm4gbWJfc3RybGVuKChzdHJpbmcpJHZhbHVlKTsKCSAgICB9OwoJICAgICR0aGlzLT5wYWRkZXIgPSBhcnJheV9zdW0oYXJyYXlfbWFwKCRmdW5jLCBhcnJheV92YWx1ZXMoJHRoaXMtPmhlYWQpKSkgKwoJCQkJICAgICAgICAgICAgICAgICAgY291bnQoYXJyYXlfdmFsdWVzKCR0aGlzLT5oZWFkKSkgLSAxOwoJfQoJCglwcml2YXRlIGZ1bmN0aW9uIGZpbGxQcmV0dHlEYXRhKGFycmF5ICRhcnIpCgl7CgkgICAgJGZ1bmMgPSBmdW5jdGlvbigkdmFsdWUpIHsKCQkgICAgcmV0dXJuIG1iX3N0cmxlbigoc3RyaW5nKSR2YWx1ZSk7CgkgICAgfTsKCQkkZGF0YUxlbnMgPSBbXTsKCQkkdGVtcCA9IGFycmF5X2NvbWJpbmUoYXJyYXlfdmFsdWVzKCR0aGlzLT50cmFpbCksCgkJCQkJCQkgYXJyYXlfbWFwKCRmdW5jLCBhcnJheV92YWx1ZXMoJGFycikpKTsKCQkKCQlmb3JlYWNoKCR0ZW1wIGFzICRsZW4xPT4kbGVuMikgewoJCQkkbGVuID0gYWJzKCRsZW4xIC0gJGxlbjIpOwoJCQkkZGF0YSA9IHN0cl9yZXBlYXQoIiAiLCAkbGVuKTsKCQkJYXJyYXlfcHVzaCgkZGF0YUxlbnMsICRkYXRhKTsKCQl9ICAgCgkJJHByZXR0eUNodW5rID0gYXJyYXlfY29tYmluZShhcnJheV92YWx1ZXMoJGFyciksCgkJCQkJCQkJCSRkYXRhTGVucyk7CQoJCQoJCWFycmF5X3B1c2goJHRoaXMtPnByZXR0eURhdGEsICRwcmV0dHlDaHVuayk7Cgl9CgkKCXByaXZhdGUgZnVuY3Rpb24gc2V0UHJpbnRhYmxlUmVzdWx0KGFycmF5ICRhcnIpCgl7CgkgICAgZm9yZWFjaCgkYXJyIGFzICRkYXRhPT4kcGFkZGluZykgewoJCSAgICAkcmVzID0gKHN0cmluZykkZGF0YSAuIChzdHJpbmcpJHBhZGRpbmc7CgkJCSR0aGlzLT5wcmludGFibGVSZXN1bHQgLj0gJHJlczsKCQkJJHRoaXMtPnByaW50YWJsZVJlc3VsdCAuPSAiICI7CgkJfQoJCSR0aGlzLT5wcmludGFibGVSZXN1bHQgLj0gKCJcbiIgLiBzdHJfcmVwZWF0KCItIiwgJHRoaXMtPnBhZGRlcikgLiAiXG4iKTsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIF9fdG9TdHJpbmcoKQoJewoJICAgIHJldHVybiAkdGhpcy0+cHJpbnRhYmxlUmVzdWx0OwoJfQoJCglwcml2YXRlIGZ1bmN0aW9uIGluaXRGb290ZXIoYXJyYXkgJGFycikKCXsKCSAgICAkYWxsV29ya2VycyA9IDA7CgkJJGFsbENvZmZlZSA9IDA7CgkJJGFsbFNhbGFyeSA9IDA7CgkJJGFsbFBhZ2VzID0gMDsKCQkkYWxsQXZnID0gW107CgkJCgkJZm9yZWFjaCgkYXJyIGFzICRzdWJhcnIpIHsKCQkgICAgJGN1cl92YWxzID0gYXJyYXlfdmFsdWVzKCRzdWJhcnIpOwoJCQkkYWxsV29ya2VycyArPSAkY3VyX3ZhbHNbMl07CgkJCSRhbGxTYWxhcnkgKz0gJGN1cl92YWxzWzNdOwoJCQkkYWxsQ29mZmVlICs9ICRjdXJfdmFsc1s0XTsKCQkJJGFsbFBhZ2VzICs9ICRjdXJfdmFsc1s1XTsKCQkJYXJyYXlfcHVzaCgkYWxsQXZnLCAkY3VyX3ZhbHNbNl0pOwoJCX0KCQkKCQkkdGhpcy0+Zm9vdFsiY29sMiJdID0gJGFsbFdvcmtlcnM7CgkJJHRoaXMtPmZvb3RbImNvbDMiXSA9ICRhbGxTYWxhcnk7CgkJJHRoaXMtPmZvb3RbImNvbDQiXSA9ICRhbGxDb2ZmZWU7CgkJJHRoaXMtPmZvb3RbImNvbDUiXSA9ICRhbGxQYWdlczsKCQkkdGhpcy0+Zm9vdFsiY29sNiJdID0gYXJyYXlfc3VtKCRhbGxBdmcpIC8gY291bnQoJGFsbEF2Zyk7Cgl9CgkKCXByaXZhdGUgZnVuY3Rpb24gc2V0UHJpbnRhYmxlRm9vdCgpCgl7CgkgICAgJHRoaXMtPmZpbGxQcmV0dHlEYXRhKCR0aGlzLT5mb290KTsKCX0KfQoKCmFic3RyYWN0IGNsYXNzIEVtcGxveWVlCnsKICAgIHByaXZhdGUgJHNhbGFyeTsKCXByaXZhdGUgJHJhbms7Cglwcml2YXRlICRjb2ZmZWVBbXQ7Cglwcml2YXRlICRwYWdlczsKCXByaXZhdGUgJGlzQm9zczsKCQoJcHVibGljIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRzYWxhcnksICRyYW5rLCAkY29mZmVlQW10LCAkcGFnZXMsICRib3NzPWZhbHNlKQoJewoJICAgICR0aGlzLT5zYWxhcnkgPSAkc2FsYXJ5OwoJCSR0aGlzLT5yYW5rID0gJHJhbms7CgkJJHRoaXMtPmNvZmZlZUFtdCA9ICRjb2ZmZWVBbXQ7CgkJJHRoaXMtPnBhZ2VzID0gJHBhZ2VzOwoJCSR0aGlzLT5pc0Jvc3MgPSAkYm9zczsKCX0JCgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRTYWxhcnkoKQoJewoJICAgIGlmICgkdGhpcy0+cmFuayA9PT0gMSkgewoJCSAgICAkc2FsYXJ5ID0gJHRoaXMtPnNhbGFyeTsKCQl9IGVsc2VpZigkdGhpcy0+cmFuayA9PT0gMikgewoJCSAgICAkc2FsYXJ5ID0gJHRoaXMtPnNhbGFyeSAqIDEuMjU7CgkJfSBlbHNlaWYoJHRoaXMtPnJhbmsgPT09IDMpIHsKCQkgICAgJHNhbGFyeSA9ICR0aGlzLT5zYWxhcnkgKiAxLjU7CgkJfSAKCQkKCQlpZigkdGhpcy0+aXNCb3NzKSB7CgkJICAgICRzYWxhcnkgKz0gJHNhbGFyeSAqIDAuNTsKCQl9CgkJCgkJcmV0dXJuICRzYWxhcnk7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRDb2ZmZWUoKQoJewoJICAgIGlmKCR0aGlzLT5pc0Jvc3MpIHsKCQkgICAgcmV0dXJuICR0aGlzLT5jb2ZmZWVBbXQgKiAyOwoJCX0KCSAgICByZXR1cm4gJHRoaXMtPmNvZmZlZUFtdDsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIGdldFBhZ2VzKCkKCXsKCSAgICBpZigkdGhpcy0+aXNCb3NzKSB7CgkJICAgIHJldHVybiAwOwoJCX0KCQlyZXR1cm4gJHRoaXMtPnBhZ2VzOwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gaXNCb3NzKCkKCXsKCSAgICByZXR1cm4gJHRoaXMtPmlzQm9zczsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIGdldFJhbmsoKQoJewoJICAgIHJldHVybiAkdGhpcy0+cmFuazsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIHNldFJhbmsoJHJhbmspCgl7CgkgICAgJHRoaXMtPnJhbmsgPSAkcmFuazsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIHNldFNhbGFyeSgkc2FsYXJ5KQoJewoJICAgICR0aGlzLT5zYWxhcnkgPSAkc2FsYXJ5OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gc2V0Q29mZmVlKCRhbXQpCgl7CgkgICAgJHRoaXMtPmNvZmZlZUFtdCA9ICRhbXQ7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBzZXRQYWdlcygkYW10KQoJewoJICAgICR0aGlzLT5wYWdlcyA9ICRhbXQ7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBzZXRCb3NzU3RhdHVzKCRzdGF0dXMpCgl7CgkgICAgJHRoaXMtPmlzQm9zcyA9ICRzdGF0dXM7Cgl9Cn0KCgpjbGFzcyBNYW5hZ2VyIGV4dGVuZHMgRW1wbG95ZWUKewp9CgoKY2xhc3MgQW5hbHlzdCBleHRlbmRzIEVtcGxveWVlCnsKfQoKCmNsYXNzIEVuZ2luZWVyIGV4dGVuZHMgRW1wbG95ZWUKewp9CgoKY2xhc3MgTWFya2V0ZXIgZXh0ZW5kcyBFbXBsb3llZQp7Cn0KCgpjbGFzcyBEZXBhcnRtZW50CnsKICAgIHByaXZhdGUgJGVtcGxveWVlcyA9IFtdOwoJcHJpdmF0ZSAkZGVwTmFtZTsKCQoJcHVibGljIGZ1bmN0aW9uIF9fY29uc3RydWN0KCRkZXBOYW1lKQoJewoJICAgICR0aGlzLT5kZXBOYW1lID0gJGRlcE5hbWU7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBhZGRFbXBsb3llZShFbXBsb3llZSAkZW1wKQkKCXsKCSAgICBhcnJheV9wdXNoKCR0aGlzLT5lbXBsb3llZXMsICRlbXApOwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gZmlyZUVtcGxveWVlKEVtcGxveWVlICRlbXApCgl7CgkgICAgaWYoaW5fYXJyYXkoJGVtcCwgJHRoaXMtPmVtcGxveWVlcywgdHJ1ZSkpIHsKICAgICAgICAgICAgJGtleSA9IGFycmF5X3NlYXJjaCgkZW1wLCAkdGhpcy0+ZW1wbG95ZWVzKTsKCQkJdW5zZXQoJHRoaXMtPmVtcGxveWVlc1ska2V5XSk7CiAgICAgICAgfQogICAgfQoJCglwdWJsaWMgZnVuY3Rpb24gc2V0TmV3Qm9zcyhFbXBsb3llZSAkZW1wKQoJewoJICAgIGZvcmVhY2goJHRoaXMtPmVtcGxveWVlcyBhcyAkZW1wbG95ZWUpIHsKCSAgICAgICAgaWYoJGVtcGxveWVlLT5pc0Jvc3MoKSkgewoJICAgICAgICAgICAgJGVtcGxveWVlLT5zZXRCb3NzU3RhdHVzKGZhbHNlKTsKCSAgICAgICAgfQoJCX0JCgkJaWYoaW5fYXJyYXkoJGVtcCwgJHRoaXMtPmVtcGxveWVlcywgdHJ1ZSkpIHsKCQkgICAgJGVtcC0+c2V0Qm9zc1N0YXR1cyh0cnVlKTsKCQl9Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRUb3RhbFNhbGFyeSgpIAoJewoJICAgICR0b3RhbFNhbGFyeSA9IDA7CgkgICAgZm9yZWFjaCgkdGhpcy0+ZW1wbG95ZWVzIGFzICRlbXBsb3llZSkgewoJICAgICAgCSR0b3RhbFNhbGFyeSArPSAkZW1wbG95ZWUtPmdldFNhbGFyeSgpOwoJCX0KCQlyZXR1cm4gJHRvdGFsU2FsYXJ5OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gZ2V0VG90YWxQYWdlcygpCgl7CgkgICAgJHRvdGFsV29ya0RvbmUgPSAwOwoJICAgIGZvcmVhY2goJHRoaXMtPmVtcGxveWVlcyBhcyAkZW1wbG95ZWUpIHsKCQkgICAgJHRvdGFsV29ya0RvbmUgKz0gJGVtcGxveWVlLT5nZXRQYWdlcygpOwoJCX0KCSAgICByZXR1cm4gJHRvdGFsV29ya0RvbmU7Cgl9CgkJCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0VG90YWxDb2ZmZWUoKSAJCgl7CgkgICAgJHRvdGFsQ29mZmVlQW1vdW50ID0gMDsKCSAgICBmb3JlYWNoKCR0aGlzLT5lbXBsb3llZXMgYXMgJGVtcGxveWVlKSB7CgkJICAgICR0b3RhbENvZmZlZUFtb3VudCArPSAkZW1wbG95ZWUtPmdldENvZmZlZSgpOwoJCX0KCSAgICByZXR1cm4gJHRvdGFsQ29mZmVlQW1vdW50OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gZ2V0RW1wbG95ZWVzTnVtKCkKCXsKCSAgICByZXR1cm4gY291bnQoJHRoaXMtPmVtcGxveWVlcyk7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRTYWxhcnlQYWdlc1JhdGlvKCkKCXsKCSAgICBpZigkdGhpcy0+Z2V0VG90YWxQYWdlcygpICE9PSAwKSB7CgkgICAgICAgIHJldHVybiAkdGhpcy0+Z2V0VG90YWxTYWxhcnkoKSAvICR0aGlzLT5nZXRUb3RhbFBhZ2VzKCk7CgkJfQoJCWV4aXQoItCSINGN0YLQvtC8INC00LXQv9Cw0YDRgtCw0LzQtdC90YLQtSDQvtC00L3QuCDQsdC10LfQtNC10LvRjNC90LjQutC4IVxuIik7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXREZXBOYW1lKCkKCXsKCSAgICByZXR1cm4gJHRoaXMtPmRlcE5hbWU7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRFbXBsb3llZXMoKQoJewoJICAgIHJldHVybiAkdGhpcy0+ZW1wbG95ZWVzOwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gX19jbG9uZSgpCgl7CgkgICAgJGNsb25lZEVtcHMgPSBbXTsKCSAgICBmb3JlYWNoKCR0aGlzLT5lbXBsb3llZXMgYXMgJGVtcCkgewoJCSAgICAkY2xvbmVkRW1wc1tdID0gY2xvbmUgJGVtcDsKCQl9CgkJJHRoaXMtPmVtcGxveWVlcyA9ICRjbG9uZWRFbXBzOwoJICAgICR0aGlzLT50b3RhbFNhbGFyeSA9IDA7CgkgICAgJHRoaXMtPnRvdGFsQ29mZmVlQW1vdW50ID0gMDsKCSAgICAkdGhpcy0+dG90YWxXb3JrRG9uZSA9IDA7CiAgICB9Cn0KCgpmdW5jdGlvbiBjcmVhdGVFbXBsb3llZShEZXBhcnRtZW50ICRkZXAsICRjbHMsICRyYW5rLCAkYW10LCAkYm9zcz1mYWxzZSkKewogICAgJGVtcFNhbGFyeXMgPSBbIk1hbmFnZXIiID0+IDUwMCwgIk1hcmtldGVyIiA9PiA0MDAsICJBbmFseXN0IiA9PiA4MDAsICJFbmdpbmVlciIgPT4gMjAwXTsKICAgICRlbXBDb2ZmZWUgPSBbIk1hbmFnZXIiID0+IDIwLCAiTWFya2V0ZXIiID0+IDE1LCAiQW5hbHlzdCIgPT4gNTAsICJFbmdpbmVlciIgPT4gNV07CiAgICAkZW1wUGFnZXMgPSBbIk1hbmFnZXIiID0+IDIwMCwgIk1hcmtldGVyIiA9PiAxNTAsICJBbmFseXN0IiA9PiA1LCAiRW5naW5lZXIiID0+IDUwXTsKCiAgICBmb3IoJGkgPSAwOyAkaSA8ICRhbXQ7ICRpKyspICAgICB7CiAgICAgICAkZW1wID0gbmV3ICRjbHMoJGVtcFNhbGFyeXNbJGNsc10sICRyYW5rLCAkZW1wQ29mZmVlWyRjbHNdLCAkZW1wUGFnZXNbJGNsc10sICRib3NzKTsKICAgICAgICRkZXAtPmFkZEVtcGxveWVlKCRlbXApOwogICAgfQp9CgoKZnVuY3Rpb24gY21wUmFua3MoRW1wbG95ZWUgJGVtcDEsIEVtcGxveWVlICRlbXAyKSAKewogICAgaWYoJGVtcDEtPmdldFJhbmsoKSA9PT0gJGVtcDItPmdldFJhbmsoKSkgewoJICAgIHJldHVybiAwOwoJfQoJcmV0dXJuICgkZW1wMS0+Z2V0UmFuaygpIDwgJGVtcDItPmdldFJhbmsoKSkgPyAtMSA6IDE7Cn0KCmZ1bmN0aW9uIHRyeU1vZGVsMShEZXBhcnRtZW50ICRkZXApCnsKICAgICRlbmdpbmVlcnMgPSBbXTsKCWZvcmVhY2goJGRlcC0+Z2V0RW1wbG95ZWVzKCkgYXMgJGVtcCkgewoJICAgIGlmKGdldF9jbGFzcygkZW1wKSA9PT0gIkVuZ2luZWVyIiAmJiAkZW1wLT5pc0Jvc3MoKSAhPT0gdHJ1ZSkgewoJCSAgICAkZW5naW5lZXJzW10gPSAkZW1wOwoJCX0JCgl9CSAKCXVzb3J0KCRlbmdpbmVlcnMsICJjbXBSYW5rcyIpOwoJJGZpcmVBbXQgPSByb3VuZChjb3VudCgkZW5naW5lZXJzKSAqIDAuNCk7CiAgICAkZmlyZWRFbmdpbmVlcnMgPSBhcnJheV9zbGljZSgkZW5naW5lZXJzLCAwLCAkZmlyZUFtdCk7CQoJZm9yZWFjaCgkZmlyZWRFbmdpbmVlcnMgYXMgJGVuZ2luZWVyKSB7CgkgICAgJGRlcC0+ZmlyZUVtcGxveWVlKCRlbmdpbmVlcik7Cgl9Cn0KCmZ1bmN0aW9uIHRyeU1vZGVsMihEZXBhcnRtZW50ICRkZXApCnsKICAgICRhbmFseXN0cyA9IFtdOwoJZm9yZWFjaCgkZGVwLT5nZXRFbXBsb3llZXMoKSBhcyAkZW1wKSB7CgkgICAgaWYoZ2V0X2NsYXNzKCRlbXApID09PSAiQW5hbHlzdCIpIHsKCSAgICAgICAgJGVtcC0+c2V0U2FsYXJ5KDExMDApOwoJICAgICAgICAkZW1wLT5zZXRDb2ZmZWUoNzUpOwoJCQkkYW5hbHlzdHNbXSA9ICRlbXA7CgkJfQoJfQoJaWYoJGFuYWx5c3RzKSB7CgkgICAgdXNvcnQoJGFuYWx5c3RzLCAiY21wUmFua3MiKTsKCSAgICBmb3JlYWNoKCRkZXAtPmdldEVtcGxveWVlcygpIGFzICRlbXApIHsKCQkgICAgaWYoJGVtcC0+aXNCb3NzKCkgJiYgZ2V0X2NsYXNzKCRlbXApICE9PSAiQW5hbHlzdCIpIHsKCSAgICAgICAgICAgICRkZXAtPnNldE5ld0Jvc3MoZW5kKCRhbmFseXN0cykpOwoJICAgICAgICB9CgkgICAgfQoJfQp9CQoKZnVuY3Rpb24gdHJ5TW9kZWwzKERlcGFydG1lbnQgJGRlcCkgCnsKCSRmaXJzdFJhbmtNYW4gPSBbXTsKCSRzZWNvbmRSYW5rTWFuID0gW107Cglmb3JlYWNoKCRkZXAtPmdldEVtcGxveWVlcygpIGFzICRlbXApIHsKCSAgICBpZihnZXRfY2xhc3MoJGVtcCkgPT09ICJNYW5hZ2VyIiAmJiAkZW1wLT5nZXRSYW5rKCkgPT09IDEgJiYgJGVtcC0+aXNCb3NzKCkgPT09IGZhbHNlKSB7CgkgICAgICAgICRmaXJzdFJhbmtNYW5bXSA9ICRlbXA7CgkJfSBlbHNlaWYoZ2V0X2NsYXNzKCRlbXApID09PSAiTWFuYWdlciIgJiYgJGVtcC0+Z2V0UmFuaygpID09PSAyICYmICRlbXAtPmlzQm9zcygpID09PSBmYWxzZSkgewoJCSAgICAkc2Vjb25kUmFua01hbltdID0gJGVtcDsKCQl9IAoJfQoJJGZpcnN0UmFua0xpbSA9IGFycmF5X3NsaWNlKCRmaXJzdFJhbmtNYW4sIDAsIHJvdW5kKGNvdW50KCRmaXJzdFJhbmtNYW4pICogMC41KSk7Cgkkc2Vjb25kUmFua0xpbSA9IGFycmF5X3NsaWNlKCRzZWNvbmRSYW5rTWFuLCAwLCByb3VuZChjb3VudCgkc2Vjb25kUmFua01hbikgKiAwLjUpKTsKICAgIGZvcmVhY2goJGZpcnN0UmFua0xpbSBhcyAkbWFuYWdlcikgewoJICAgICRtYW5hZ2VyLT5zZXRSYW5rKDIpOwoJfQoJZm9yZWFjaCgkc2Vjb25kUmFua0xpbSBhcyAkbWFuYWdlcikgewoJICAgICRtYW5hZ2VyLT5zZXRSYW5rKDMpOwoJfQp9CgoKJHB1cmNoYXNlRGVwID0gbmV3IERlcGFydG1lbnQoItC30LDQutGD0L/QvtC6Iik7CmNyZWF0ZUVtcGxveWVlKCRwdXJjaGFzZURlcCwgIk1hbmFnZXIiLCAxLCA5KTsKY3JlYXRlRW1wbG95ZWUoJHB1cmNoYXNlRGVwLCAiTWFuYWdlciIsIDIsIDMpOwpjcmVhdGVFbXBsb3llZSgkcHVyY2hhc2VEZXAsICJNYW5hZ2VyIiwgMywgMik7CmNyZWF0ZUVtcGxveWVlKCRwdXJjaGFzZURlcCwgIk1hcmtldGVyIiwgMSwgMik7CmNyZWF0ZUVtcGxveWVlKCRwdXJjaGFzZURlcCwgIk1hbmFnZXIiLCAyLCAxLCB0cnVlKTsKCiRzYWxlc0RlcCA9IG5ldyBEZXBhcnRtZW50KCLQv9GA0L7QtNCw0LYiKTsKY3JlYXRlRW1wbG95ZWUoJHNhbGVzRGVwLCAiTWFuYWdlciIsIDEsIDEyKTsKY3JlYXRlRW1wbG95ZWUoJHNhbGVzRGVwLCAiTWFya2V0ZXIiLCAxLCA2KTsKY3JlYXRlRW1wbG95ZWUoJHNhbGVzRGVwLCAiQW5hbHlzdCIsIDEsIDMpOwpjcmVhdGVFbXBsb3llZSgkc2FsZXNEZXAsICJBbmFseXN0IiwgMiwgMik7CmNyZWF0ZUVtcGxveWVlKCRzYWxlc0RlcCwgIk1hcmtldGVyIiwgMiwgMSwgdHJ1ZSk7CgokYWRzRGVwID0gbmV3IERlcGFydG1lbnQoItGA0LXQutC70LDQvNGLIik7CmNyZWF0ZUVtcGxveWVlKCRhZHNEZXAsICJNYXJrZXRlciIsIDEsIDE1KTsKY3JlYXRlRW1wbG95ZWUoJGFkc0RlcCwgIk1hcmtldGVyIiwgMiwgMTApOwpjcmVhdGVFbXBsb3llZSgkYWRzRGVwLCAiTWFuYWdlciIsIDEsIDgpOwpjcmVhdGVFbXBsb3llZSgkYWRzRGVwLCAiRW5naW5lZXIiLCAxLCAyKTsKY3JlYXRlRW1wbG95ZWUoJGFkc0RlcCwgIk1hcmtldGVyIiwgMywgMSwgdHJ1ZSk7CgokbG9naXN0aWNzRGVwID0gbmV3IERlcGFydG1lbnQoItC70L7Qs9C40YHRgtC40LrQuCIpOwpjcmVhdGVFbXBsb3llZSgkbG9naXN0aWNzRGVwLCAiTWFuYWdlciIsIDEsIDEzKTsKY3JlYXRlRW1wbG95ZWUoJGxvZ2lzdGljc0RlcCwgIk1hbmFnZXIiLCAyLCA1KTsKY3JlYXRlRW1wbG95ZWUoJGxvZ2lzdGljc0RlcCwgIkVuZ2luZWVyIiwgMSwgNSk7CmNyZWF0ZUVtcGxveWVlKCRsb2dpc3RpY3NEZXAsICJNYW5hZ2VyIiwgMSwgMSwgdHJ1ZSk7CgokYWxsRGVwcyA9IFskcHVyY2hhc2VEZXAsICRzYWxlc0RlcCwgJGFkc0RlcCwgJGxvZ2lzdGljc0RlcF07CgpmdW5jdGlvbiBjbG9uZURlcGFydG1lbnRzKGFycmF5ICRkZXBhcnRtZW50cykgewoJJGNsb25lZERlcHMgPSBbXTsKCWZvcmVhY2goJGRlcGFydG1lbnRzIGFzICRkZXApIHsKCQkkY2xvbmVkRGVwc1tdID0gY2xvbmUgJGRlcDsKCX0KCXJldHVybiAkY2xvbmVkRGVwczsKfQkKCmZ1bmN0aW9uIHRyeUNyaXNpc01vZGVsKGFycmF5ICRjbG9uZWREZXBzLCBjYWxsYWJsZSAkbW9kZWxGdW5jLCAkZGVzY3JpcHRpb24pCnsgCiAgICBhcnJheV93YWxrKCRjbG9uZWREZXBzLCAkbW9kZWxGdW5jKTsKCSRyZXN1bHQgPSBuZXcgUHJldHR5UHJpbnRlcigkY2xvbmVkRGVwcyk7CgllY2hvICJcblxuIjsKICAgIGVjaG8gItCf0YDQuNC80LXQvdC10L3QuNC1INCw0YLQvdC60YDQuNC30LjRgdC90L7QuSDQvNC+0LTQtdC70Lg6IHskZGVzY3JpcHRpb259XG5cbiI7CgllY2hvICRyZXN1bHQ7Cn0KCiRiYXNlRGF0YSA9IG5ldyBQcmV0dHlQcmludGVyKCRhbGxEZXBzKTsKJGNsb25lZERlcHMxID0gY2xvbmVEZXBhcnRtZW50cygkYWxsRGVwcyk7CiRjbG9uZWREZXBzMiA9IGNsb25lRGVwYXJ0bWVudHMoJGFsbERlcHMpOwokY2xvbmVkRGVwczMgPSBjbG9uZURlcGFydG1lbnRzKCRhbGxEZXBzKTsKCmVjaG8gItCd0LDRh9Cw0LvRjNC90YvQtSDQtNCw0L3QvdGL0LUuXG5cbiI7CmVjaG8gJGJhc2VEYXRhOwoKdHJ5Q3Jpc2lzTW9kZWwoJGNsb25lZERlcHMxLCAidHJ5TW9kZWwxIiwgItGD0LLQvtC70YzQvdC10L3QuNC1IDQwJSDQuNC90LbQtdC90LXRgNC+0LIiKTsKdHJ5Q3Jpc2lzTW9kZWwoJGNsb25lZERlcHMyLCAidHJ5TW9kZWwyIiwgItC/0L7QstGL0YjQtdC90LjQtSDRg9GB0LvQvtCy0LjQuSDRgtGA0YPQtNCwINCw0L3QsNC70LjRgtC40LrQvtCyIik7CnRyeUNyaXNpc01vZGVsKCRjbG9uZWREZXBzMywgInRyeU1vZGVsMyIsICLQv9C+0LLRi9GI0LXQvdC40LUgMSDQuCAyINGA0LDQvdCz0L7QsiDRgyA1MCUg0LzQtdC90LXQtNC20LXRgNC+0LIiKTsKCj8+