<?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 $totalSalary;
private $totalCoffeeAmount;
private $totalWorkDone;
private $employees = [];
private $depName;
public function __construct($depName)
{
$this->depName = $depName;
}
public function addEmployee(Employee $emp)
{
}
public function fireEmployee(Employee $emp)
{
unset($this->employees[$key]); }
}
public function getTotalSalary()
{
$this->totalSalary = 0;
foreach($this->employees as $employee) {
$this->totalSalary += $employee->getSalary();
}
return $this->totalSalary;
}
public function getTotalPages()
{
$this->totalWorkDone = 0;
foreach($this->employees as $employee) {
$this->totalWorkDone += $employee->getPages();
}
return $this->totalWorkDone;
}
public function getTotalCoffee()
{
$this->totalCoffeeAmount = 0;
foreach($this->employees as $employee) {
$this->totalCoffeeAmount += $employee->getCoffee();
}
return $this->totalCoffeeAmount;
}
public function getEmployeesNum()
{
return count($this->employees); }
public function getSalaryPagesRatio()
{
if($this->totalWorkDone !== 0) {
return $this->totalSalary / $this->totalWorkDone;
}
exit("Division by zero"); }
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") { $emp->setBossStatus(false);
$newBoss = max($analysts); $newBoss->setBossStatus(true);
}
}
}
}
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, $boss=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, $boss=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, $boss=true);
$logisticsDep = new Department("логистики");
createEmployee($logisticsDep, "Manager", 1, 13);
createEmployee($logisticsDep, "Manager", 2, 5);
createEmployee($logisticsDep, "Engineer", 1, 5);
createEmployee($logisticsDep, "Manager", 1, 1, $boss=true);
$allDeps = [$purchaseDep, $salesDep, $adsDep, $logisticsDep];
$clonedDeps1 = [];
$clonedDeps2 = [];
$clonedDeps3 = [];
foreach($allDeps as $department) {
$clonedDeps1[] = clone $department;
$clonedDeps2[] = clone $department;
$clonedDeps3[] = clone $department;
}
function tryCrisisModel
(array $clonedDeps, callable
$modelFunc, $description) {
$result = new PrettyPrinter($clonedDeps);
echo "\n\n";
echo "Применение атнкризисной модели: {$description}\n\n";
echo $result;
}
$baseData = new PrettyPrinter($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+cmFuazsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIHNldFJhbmsoJHJhbmspCgl7CgkgICAgJHRoaXMtPnJhbmsgPSAkcmFuazsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIHNldFNhbGFyeSgkc2FsYXJ5KQoJewoJICAgICR0aGlzLT5zYWxhcnkgPSAkc2FsYXJ5OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gc2V0Q29mZmVlKCRhbXQpCgl7CgkgICAgJHRoaXMtPmNvZmZlZUFtdCA9ICRhbXQ7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBzZXRQYWdlcygkYW10KQoJewoJICAgICR0aGlzLT5wYWdlcyA9ICRhbXQ7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBzZXRCb3NzU3RhdHVzKCRzdGF0dXMpCgl7CgkgICAgJHRoaXMtPmlzQm9zcyA9ICRzdGF0dXM7Cgl9Cn0KCgpjbGFzcyBNYW5hZ2VyIGV4dGVuZHMgRW1wbG95ZWUKewp9CgoKY2xhc3MgQW5hbHlzdCBleHRlbmRzIEVtcGxveWVlCnsKfQoKCmNsYXNzIEVuZ2luZWVyIGV4dGVuZHMgRW1wbG95ZWUKewp9CgoKY2xhc3MgTWFya2V0ZXIgZXh0ZW5kcyBFbXBsb3llZQp7Cn0KCgpjbGFzcyBEZXBhcnRtZW50CnsKICAgIHByaXZhdGUgJHRvdGFsU2FsYXJ5OwoJcHJpdmF0ZSAkdG90YWxDb2ZmZWVBbW91bnQ7Cglwcml2YXRlICR0b3RhbFdvcmtEb25lOwogICAgcHJpdmF0ZSAkZW1wbG95ZWVzID0gW107Cglwcml2YXRlICRkZXBOYW1lOwoJCglwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoJGRlcE5hbWUpCgl7CgkgICAgJHRoaXMtPmRlcE5hbWUgPSAkZGVwTmFtZTsKCX0KCQogICAgcHVibGljIGZ1bmN0aW9uIGFkZEVtcGxveWVlKEVtcGxveWVlICRlbXApCQoJewoJICAgIGFycmF5X3B1c2goJHRoaXMtPmVtcGxveWVlcywgJGVtcCk7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBmaXJlRW1wbG95ZWUoRW1wbG95ZWUgJGVtcCkKCXsKCSAgICBpZihpbl9hcnJheSgkZW1wLCAkdGhpcy0+ZW1wbG95ZWVzKSkgewogICAgICAgICAgICAka2V5ID0gYXJyYXlfc2VhcmNoKCRlbXAsICR0aGlzLT5lbXBsb3llZXMpOwoJCQl1bnNldCgkdGhpcy0+ZW1wbG95ZWVzWyRrZXldKTsKICAgICAgICB9CiAgICB9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRUb3RhbFNhbGFyeSgpIAoJewoJICAgICR0aGlzLT50b3RhbFNhbGFyeSA9IDA7CgkgICAgZm9yZWFjaCgkdGhpcy0+ZW1wbG95ZWVzIGFzICRlbXBsb3llZSkgewoJICAgICAgCSR0aGlzLT50b3RhbFNhbGFyeSArPSAkZW1wbG95ZWUtPmdldFNhbGFyeSgpOwoJCX0KCQlyZXR1cm4gJHRoaXMtPnRvdGFsU2FsYXJ5OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gZ2V0VG90YWxQYWdlcygpCgl7CgkgICAgJHRoaXMtPnRvdGFsV29ya0RvbmUgPSAwOwoJICAgIGZvcmVhY2goJHRoaXMtPmVtcGxveWVlcyBhcyAkZW1wbG95ZWUpIHsKCQkgICAgJHRoaXMtPnRvdGFsV29ya0RvbmUgKz0gJGVtcGxveWVlLT5nZXRQYWdlcygpOwoJCX0KCSAgICByZXR1cm4gJHRoaXMtPnRvdGFsV29ya0RvbmU7Cgl9CgkJCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2V0VG90YWxDb2ZmZWUoKSAJCgl7CgkgICAgJHRoaXMtPnRvdGFsQ29mZmVlQW1vdW50ID0gMDsKCSAgICBmb3JlYWNoKCR0aGlzLT5lbXBsb3llZXMgYXMgJGVtcGxveWVlKSB7CgkJICAgICR0aGlzLT50b3RhbENvZmZlZUFtb3VudCArPSAkZW1wbG95ZWUtPmdldENvZmZlZSgpOwoJCX0KCSAgICByZXR1cm4gJHRoaXMtPnRvdGFsQ29mZmVlQW1vdW50OwoJfQoJCglwdWJsaWMgZnVuY3Rpb24gZ2V0RW1wbG95ZWVzTnVtKCkKCXsKCSAgICByZXR1cm4gY291bnQoJHRoaXMtPmVtcGxveWVlcyk7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBnZXRTYWxhcnlQYWdlc1JhdGlvKCkKCXsKCSAgICBpZigkdGhpcy0+dG90YWxXb3JrRG9uZSAhPT0gMCkgewoJICAgICAgICByZXR1cm4gJHRoaXMtPnRvdGFsU2FsYXJ5IC8gJHRoaXMtPnRvdGFsV29ya0RvbmU7CgkJfQoJCWV4aXQoIkRpdmlzaW9uIGJ5IHplcm8iKTsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIGdldERlcE5hbWUoKQoJewoJICAgIHJldHVybiAkdGhpcy0+ZGVwTmFtZTsKCX0KCQoJcHVibGljIGZ1bmN0aW9uIGdldEVtcGxveWVlcygpCgl7CgkgICAgcmV0dXJuICR0aGlzLT5lbXBsb3llZXM7Cgl9CgkKCXB1YmxpYyBmdW5jdGlvbiBfX2Nsb25lKCkKCXsKCSAgICAkY2xvbmVkRW1wcyA9IFtdOwoJICAgIGZvcmVhY2goJHRoaXMtPmVtcGxveWVlcyBhcyAkZW1wKSB7CgkJICAgICRjbG9uZWRFbXBzW10gPSBjbG9uZSAkZW1wOwoJCX0KCQkkdGhpcy0+ZW1wbG95ZWVzID0gJGNsb25lZEVtcHM7CgkgICAgJHRoaXMtPnRvdGFsU2FsYXJ5ID0gMDsKCSAgICAkdGhpcy0+dG90YWxDb2ZmZWVBbW91bnQgPSAwOwoJICAgICR0aGlzLT50b3RhbFdvcmtEb25lID0gMDsKICAgIH0KfQoKCmZ1bmN0aW9uIGNyZWF0ZUVtcGxveWVlKERlcGFydG1lbnQgJGRlcCwgJGNscywgJHJhbmssICRhbXQsICRib3NzPWZhbHNlKQp7CiAgICAkZW1wU2FsYXJ5cyA9IFsiTWFuYWdlciIgPT4gNTAwLCAiTWFya2V0ZXIiID0+IDQwMCwgIkFuYWx5c3QiID0+IDgwMCwgIkVuZ2luZWVyIiA9PiAyMDBdOwogICAgJGVtcENvZmZlZSA9IFsiTWFuYWdlciIgPT4gMjAsICJNYXJrZXRlciIgPT4gMTUsICJBbmFseXN0IiA9PiA1MCwgIkVuZ2luZWVyIiA9PiA1XTsKICAgICRlbXBQYWdlcyA9IFsiTWFuYWdlciIgPT4gMjAwLCAiTWFya2V0ZXIiID0+IDE1MCwgIkFuYWx5c3QiID0+IDUsICJFbmdpbmVlciIgPT4gNTBdOwoKICAgIGZvcigkaSA9IDA7ICRpIDwgJGFtdDsgJGkrKykgICAgIHsKICAgICAgICRlbXAgPSBuZXcgJGNscygkZW1wU2FsYXJ5c1skY2xzXSwgJHJhbmssICRlbXBDb2ZmZWVbJGNsc10sICRlbXBQYWdlc1skY2xzXSwgJGJvc3MpOwogICAgICAgJGRlcC0+YWRkRW1wbG95ZWUoJGVtcCk7CiAgICB9Cn0KCgpmdW5jdGlvbiBjbXBSYW5rcyhFbXBsb3llZSAkZW1wMSwgRW1wbG95ZWUgJGVtcDIpIAp7CiAgICBpZigkZW1wMS0+Z2V0UmFuaygpID09PSAkZW1wMi0+Z2V0UmFuaygpKSB7CgkgICAgcmV0dXJuIDA7Cgl9CglyZXR1cm4gKCRlbXAxLT5nZXRSYW5rKCkgPCAkZW1wMi0+Z2V0UmFuaygpKSA/IC0xIDogMTsKfQoKZnVuY3Rpb24gdHJ5TW9kZWwxKERlcGFydG1lbnQgJGRlcCkKewogICAgJGVuZ2luZWVycyA9IFtdOwoJZm9yZWFjaCgkZGVwLT5nZXRFbXBsb3llZXMoKSBhcyAkZW1wKSB7CgkgICAgaWYoZ2V0X2NsYXNzKCRlbXApID09PSAiRW5naW5lZXIiICYmICRlbXAtPmlzQm9zcygpICE9PSB0cnVlKSB7CgkJICAgICRlbmdpbmVlcnNbXSA9ICRlbXA7CgkJfQkKCX0JIAoJdXNvcnQoJGVuZ2luZWVycywgImNtcFJhbmtzIik7CgkkZmlyZUFtdCA9IHJvdW5kKGNvdW50KCRlbmdpbmVlcnMpICogMC40KTsKICAgICRmaXJlZEVuZ2luZWVycyA9IGFycmF5X3NsaWNlKCRlbmdpbmVlcnMsIDAsICRmaXJlQW10KTsJCglmb3JlYWNoKCRmaXJlZEVuZ2luZWVycyBhcyAkZW5naW5lZXIpIHsKCSAgICAkZGVwLT5maXJlRW1wbG95ZWUoJGVuZ2luZWVyKTsKCX0KfQoKZnVuY3Rpb24gdHJ5TW9kZWwyKERlcGFydG1lbnQgJGRlcCkKewogICAgJGFuYWx5c3RzID0gW107Cglmb3JlYWNoKCRkZXAtPmdldEVtcGxveWVlcygpIGFzICRlbXApIHsKCSAgICBpZihnZXRfY2xhc3MoJGVtcCkgPT09ICJBbmFseXN0IikgewoJICAgICAgICAkZW1wLT5zZXRTYWxhcnkoMTEwMCk7CgkgICAgICAgICRlbXAtPnNldENvZmZlZSg3NSk7CgkJCSRhbmFseXN0c1tdID0gJGVtcDsKCQl9Cgl9CglpZigkYW5hbHlzdHMpIHsKCSAgICB1c29ydCgkYW5hbHlzdHMsICJjbXBSYW5rcyIpOwoJICAgIGZvcmVhY2goJGRlcC0+Z2V0RW1wbG95ZWVzKCkgYXMgJGVtcCkgewoJICAgICAgICBpZigkZW1wLT5pc0Jvc3MoKSAmJiBnZXRfY2xhc3MoJGVtcCkgIT09ICJBbmFseXN0IikgewoJICAgICAgICAgICAgJGVtcC0+c2V0Qm9zc1N0YXR1cyhmYWxzZSk7CgkgICAgICAgICAgICAkbmV3Qm9zcyA9IG1heCgkYW5hbHlzdHMpOwoJCQkJJG5ld0Jvc3MtPnNldEJvc3NTdGF0dXModHJ1ZSk7CgkgICAgICAgIH0KCSAgICB9Cgl9Cn0JCgpmdW5jdGlvbiB0cnlNb2RlbDMoRGVwYXJ0bWVudCAkZGVwKSAKewoJJGZpcnN0UmFua01hbiA9IFtdOwoJJHNlY29uZFJhbmtNYW4gPSBbXTsKCWZvcmVhY2goJGRlcC0+Z2V0RW1wbG95ZWVzKCkgYXMgJGVtcCkgewoJICAgIGlmKGdldF9jbGFzcygkZW1wKSA9PT0gIk1hbmFnZXIiICYmICRlbXAtPmdldFJhbmsoKSA9PT0gMSAmJiAkZW1wLT5pc0Jvc3MoKSA9PT0gZmFsc2UpIHsKCSAgICAgICAgJGZpcnN0UmFua01hbltdID0gJGVtcDsKCQl9IGVsc2VpZihnZXRfY2xhc3MoJGVtcCkgPT09ICJNYW5hZ2VyIiAmJiAkZW1wLT5nZXRSYW5rKCkgPT09IDIgJiYgJGVtcC0+aXNCb3NzKCkgPT09IGZhbHNlKSB7CgkJICAgICRzZWNvbmRSYW5rTWFuW10gPSAkZW1wOwoJCX0gCgl9CgkkZmlyc3RSYW5rTGltID0gYXJyYXlfc2xpY2UoJGZpcnN0UmFua01hbiwgMCwgcm91bmQoY291bnQoJGZpcnN0UmFua01hbikgKiAwLjUpKTsKCSRzZWNvbmRSYW5rTGltID0gYXJyYXlfc2xpY2UoJHNlY29uZFJhbmtNYW4sIDAsIHJvdW5kKGNvdW50KCRzZWNvbmRSYW5rTWFuKSAqIDAuNSkpOwogICAgZm9yZWFjaCgkZmlyc3RSYW5rTGltIGFzICRtYW5hZ2VyKSB7CgkgICAgJG1hbmFnZXItPnNldFJhbmsoMik7Cgl9Cglmb3JlYWNoKCRzZWNvbmRSYW5rTGltIGFzICRtYW5hZ2VyKSB7CgkgICAgJG1hbmFnZXItPnNldFJhbmsoMyk7Cgl9Cn0KCgokcHVyY2hhc2VEZXAgPSBuZXcgRGVwYXJ0bWVudCgi0LfQsNC60YPQv9C+0LoiKTsKY3JlYXRlRW1wbG95ZWUoJHB1cmNoYXNlRGVwLCAiTWFuYWdlciIsIDEsIDkpOwpjcmVhdGVFbXBsb3llZSgkcHVyY2hhc2VEZXAsICJNYW5hZ2VyIiwgMiwgMyk7CmNyZWF0ZUVtcGxveWVlKCRwdXJjaGFzZURlcCwgIk1hbmFnZXIiLCAzLCAyKTsKY3JlYXRlRW1wbG95ZWUoJHB1cmNoYXNlRGVwLCAiTWFya2V0ZXIiLCAxLCAyKTsKY3JlYXRlRW1wbG95ZWUoJHB1cmNoYXNlRGVwLCAiTWFuYWdlciIsIDIsIDEsICRib3NzPXRydWUpOwoKJHNhbGVzRGVwID0gbmV3IERlcGFydG1lbnQoItC/0YDQvtC00LDQtiIpOwpjcmVhdGVFbXBsb3llZSgkc2FsZXNEZXAsICJNYW5hZ2VyIiwgMSwgMTIpOwpjcmVhdGVFbXBsb3llZSgkc2FsZXNEZXAsICJNYXJrZXRlciIsIDEsIDYpOwpjcmVhdGVFbXBsb3llZSgkc2FsZXNEZXAsICJBbmFseXN0IiwgMSwgMyk7CmNyZWF0ZUVtcGxveWVlKCRzYWxlc0RlcCwgIkFuYWx5c3QiLCAyLCAyKTsKY3JlYXRlRW1wbG95ZWUoJHNhbGVzRGVwLCAiTWFya2V0ZXIiLCAyLCAxLCAkYm9zcz10cnVlKTsKCiRhZHNEZXAgPSBuZXcgRGVwYXJ0bWVudCgi0YDQtdC60LvQsNC80YsiKTsKY3JlYXRlRW1wbG95ZWUoJGFkc0RlcCwgIk1hcmtldGVyIiwgMSwgMTUpOwpjcmVhdGVFbXBsb3llZSgkYWRzRGVwLCAiTWFya2V0ZXIiLCAyLCAxMCk7CmNyZWF0ZUVtcGxveWVlKCRhZHNEZXAsICJNYW5hZ2VyIiwgMSwgOCk7CmNyZWF0ZUVtcGxveWVlKCRhZHNEZXAsICJFbmdpbmVlciIsIDEsIDIpOwpjcmVhdGVFbXBsb3llZSgkYWRzRGVwLCAiTWFya2V0ZXIiLCAzLCAxLCAkYm9zcz10cnVlKTsKCiRsb2dpc3RpY3NEZXAgPSBuZXcgRGVwYXJ0bWVudCgi0LvQvtCz0LjRgdGC0LjQutC4Iik7CmNyZWF0ZUVtcGxveWVlKCRsb2dpc3RpY3NEZXAsICJNYW5hZ2VyIiwgMSwgMTMpOwpjcmVhdGVFbXBsb3llZSgkbG9naXN0aWNzRGVwLCAiTWFuYWdlciIsIDIsIDUpOwpjcmVhdGVFbXBsb3llZSgkbG9naXN0aWNzRGVwLCAiRW5naW5lZXIiLCAxLCA1KTsKY3JlYXRlRW1wbG95ZWUoJGxvZ2lzdGljc0RlcCwgIk1hbmFnZXIiLCAxLCAxLCAkYm9zcz10cnVlKTsKCiRhbGxEZXBzID0gWyRwdXJjaGFzZURlcCwgJHNhbGVzRGVwLCAkYWRzRGVwLCAkbG9naXN0aWNzRGVwXTsKJGNsb25lZERlcHMxID0gW107CiRjbG9uZWREZXBzMiA9IFtdOwokY2xvbmVkRGVwczMgPSBbXTsKCmZvcmVhY2goJGFsbERlcHMgYXMgJGRlcGFydG1lbnQpIHsKICAgICRjbG9uZWREZXBzMVtdID0gY2xvbmUgJGRlcGFydG1lbnQ7CgkkY2xvbmVkRGVwczJbXSA9IGNsb25lICRkZXBhcnRtZW50OwoJJGNsb25lZERlcHMzW10gPSBjbG9uZSAkZGVwYXJ0bWVudDsKfQoKZnVuY3Rpb24gdHJ5Q3Jpc2lzTW9kZWwoYXJyYXkgJGNsb25lZERlcHMsIGNhbGxhYmxlICRtb2RlbEZ1bmMsICRkZXNjcmlwdGlvbikKeyAKICAgIGFycmF5X3dhbGsoJGNsb25lZERlcHMsICRtb2RlbEZ1bmMpOwoJJHJlc3VsdCA9IG5ldyBQcmV0dHlQcmludGVyKCRjbG9uZWREZXBzKTsKCWVjaG8gIlxuXG4iOwogICAgZWNobyAi0J/RgNC40LzQtdC90LXQvdC40LUg0LDRgtC90LrRgNC40LfQuNGB0L3QvtC5INC80L7QtNC10LvQuDogeyRkZXNjcmlwdGlvbn1cblxuIjsKCWVjaG8gJHJlc3VsdDsKfQoKJGJhc2VEYXRhID0gbmV3IFByZXR0eVByaW50ZXIoJGFsbERlcHMpOwplY2hvICLQndCw0YfQsNC70YzQvdGL0LUg0LTQsNC90L3Ri9C1LlxuXG4iOwplY2hvICRiYXNlRGF0YTsKCnRyeUNyaXNpc01vZGVsKCRjbG9uZWREZXBzMSwgInRyeU1vZGVsMSIsICLRg9Cy0L7Qu9GM0L3QtdC90LjQtSA0MCUg0LjQvdC20LXQvdC10YDQvtCyIik7CnRyeUNyaXNpc01vZGVsKCRjbG9uZWREZXBzMiwgInRyeU1vZGVsMiIsICLQv9C+0LLRi9GI0LXQvdC40LUg0YPRgdC70L7QstC40Lkg0YLRgNGD0LTQsCDQsNC90LDQu9C40YLQuNC60L7QsiIpOwp0cnlDcmlzaXNNb2RlbCgkY2xvbmVkRGVwczMsICJ0cnlNb2RlbDMiLCAi0L/QvtCy0YvRiNC10L3QuNC1IDEg0LggMiDRgNCw0L3Qs9C+0LIg0YMgNTAlINC80LXQvdC10LTQttC10YDQvtCyIik7Cgo/Pg==