<?php
/**
* input.php
*/
$input = [
// count, profession, grade, [chief]
'Purchasing' => [
[9, Employee::MANAGER, 1],
[3, Employee::MANAGER, 2],
[2, Employee::MANAGER, 3],
[2, Employee::MARKETER, 1],
[1, Employee::MANAGER, 2, true]
],
'Sales' => [
[12, Employee::MANAGER, 1],
[6, Employee::MARKETER, 1],
[3, Employee::ANALYST, 1],
[2, Employee::ANALYST, 2],
[1, Employee::MARKETER, 2, true]
],
'Advertising' => [
[15, Employee::MARKETER, 1],
[10, Employee::MARKETER, 2],
[8, Employee::MANAGER, 1],
[2, Employee::ENGINEER, 1],
[1, Employee::MARKETER, 3, true]
],
'Logistics' => [
[13, Employee::MANAGER, 1],
[5, Employee::MANAGER, 2],
[5, Employee::ENGINEER, 1],
[1, Employee::MANAGER, 1, true]
]
];
/**
* classes.php
*/
class Company {
protected array $departments; protected int $numOfDepts;
public function __construct
(array $input) { $departments = [];
foreach ($input as $department => $employees) {
$departments[] = new Department($department, $employees);
}
$this->departments = $departments;
$this->numOfDepts = count($departments); }
public function getDepartments
(): array { return $this->departments;
}
public function getTotalStaff(): int {
$staff = 0;
foreach ($this->departments as $dept) {
$staff += $dept->getStaffNumber();
}
return $staff;
}
public function getTotalLaborCost() {
$cost = 0;
foreach ($this->departments as $dept) {
$cost += $dept->getLaborCost();
}
return $cost;
}
public function getTotalCoffeeDrunk() {
$amount = 0;
foreach ($this->departments as $dept) {
$amount += $dept->getCoffeeDrunk();
}
return $amount;
}
public function getTotalPagesProduced(): int {
$pages = 0;
foreach ($this->departments as $dept) {
$pages += $dept->getPagesProduced();
}
return $pages;
}
public function getTotalCostPerPage() {
$cost = 0;
foreach ($this->departments as $dept) {
$cost += $dept->getCostPerPage();
}
return $cost;
}
public function getAverageStaff() {
$staff = 0;
foreach ($this->departments as $dept) {
$staff += $dept->getStaffNumber();
}
return $staff / $this->numOfDepts;
}
public function getAverageLaborCost() {
$cost = 0;
foreach ($this->departments as $dept) {
$cost += $dept->getLaborCost();
}
return $cost / $this->numOfDepts;
}
public function getAverageCoffeeDrunk() {
$amount = 0;
foreach ($this->departments as $dept) {
$amount += $dept->getCoffeeDrunk();
}
return $amount / $this->numOfDepts;
}
public function getAveragePagesProduced() {
$pages = 0;
foreach ($this->departments as $dept) {
$pages += $dept->getPagesProduced();
}
return $pages / $this->numOfDepts;
}
public function getAverageCostPerPage() {
$cost = 0;
foreach ($this->departments as $dept) {
$cost += $dept->getCostPerPage();
}
return $cost / $this->numOfDepts;
}
public function printReport() {
$firstCol = 20;
$regCol = 15;
echo padString('DEPARTMENT', $firstCol) . padString('STAFF', $regCol, 'left') . padString('LABOR COST', $regCol, 'left') . padString('COFFEE DRUNK', $regCol, 'left') . padString('PAGES', $regCol, 'left') . padString('COST PER PAGE', $regCol, 'left') . "\n";
echo padString('=', $firstCol, 'right', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . "\n";
foreach ($this->getDepartments() as $department) {
echo padString($department->getDeptName(), $firstCol) . padString($department->getStaffNumber(), $regCol, 'left') . padString($department->getLaborCost(), $regCol, 'left') . padString($department->getCoffeeDrunk(), $regCol, 'left') . padString($department->getPagesProduced(), $regCol, 'left') . padString($department->getCostPerPage(), $regCol, 'left') . "\n";
}
echo padString('=', $firstCol, 'right', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . padString('=', $regCol, 'left', '=') . "\n";
echo padString('TOTAL', $firstCol) . padString($this->getTotalStaff(), $regCol, 'left') . padString($this->getTotalLaborCost(), $regCol, 'left') . padString($this->getTotalCoffeeDrunk(), $regCol, 'left') . padString($this->getTotalPagesProduced(), $regCol, 'left') . padString($this->getTotalCostPerPage(), $regCol, 'left') . "\n";
echo padString('AVERAGE', $firstCol) . padString($this->getAverageStaff(), $regCol, 'left') . padString($this->getAverageLaborCost(), $regCol, 'left') . padString($this->getAverageCoffeeDrunk(), $regCol, 'left') . padString($this->getAveragePagesProduced(), $regCol, 'left') . padString($this->getAverageCostPerPage(), $regCol, 'left') . "\n";
}
}
class Department {
protected string $name;
public function __construct
(string
$name, array $employees) { $this->name = $name;
$this->staff = [];
foreach ($employees as $empGroup) {
$empQuantity = $empGroup[0];
$empType = $empGroup[1];
$empGrade = $empGroup[2]; // 1
$empChief = isset($empGroup[3]) ?
true : false; for ($c = 0; $c < $empQuantity; $c++) {
$this->staff[] = new $empType($empGrade, $empChief);
}
}
}
public function getDeptName(): string {
return $this->name;
}
public function getStaffNumber(): int {
$staffNumber = count($this->staff); return $staffNumber;
}
public function getLaborCost(): int {
$aggregateCost = 0;
foreach ($this->staff as $employee) {
$aggregateCost += $employee->getActualPay();
}
return $aggregateCost;
}
public function getCoffeeDrunk(): int {
$totalCoffeeDrunk = 0;
foreach ($this->staff as $employee) {
$totalCoffeeDrunk += $employee->getActualCoffeeConsumption();
}
return $totalCoffeeDrunk;
}
public function getPagesProduced() {
$totalPagesProduced = 0;
foreach ($this->staff as $employee) {
$totalPagesProduced += $employee->getActualPaperworkProduced();
}
return $totalPagesProduced;
}
public function getCostPerPage() {
$pages = $this->getPagesProduced();
$laborCost = $this->getLaborCost();
return round($laborCost / $pages, 2); }
}
abstract class Employee {
const MANAGER = "Manager";
const MARKETER = "Marketer";
const ENGINEER = "Engineer";
const ANALYST = "Analyst";
protected int $grade;
protected $baseRate;
protected bool $chief;
protected $baseCoffeeConsumption;
protected int $basePaperworkProduced;
public function __construct(int $grade, bool $chief = false) {
$this->grade = $grade;
$this->chief = $chief;
}
public function getActualPay() {
$rate = $this->baseRate;
if ($this->grade == 2) {
$rate *= 1.25;
} elseif ($this->grade == 3) {
$rate = $rate * 1.5;
}
return $this->chief ? $rate * 2 : $rate;
}
public function getActualCoffeeConsumption() {
return $this->chief ? $this->baseCoffeeConsumption * 2 : $this->baseCoffeeConsumption;
}
public function getActualPaperworkProduced(): int {
return $this->chief ? 0 : $this->basePaperworkProduced;
}
}
class Manager extends Employee {
protected $baseRate = 500;
protected $baseCoffeeConsumption = 20;
protected int $basePaperworkProduced = 200;
}
class Marketer extends Employee {
protected $baseRate = 400;
protected $baseCoffeeConsumption = 15;
protected int $basePaperworkProduced = 150;
}
class Engineer extends Employee {
protected $baseRate = 200;
protected $baseCoffeeConsumption = 5;
protected int $basePaperworkProduced = 50;
}
class Analyst extends Employee {
protected $baseRate = 800;
protected $baseCoffeeConsumption = 50;
protected int $basePaperworkProduced = 5;
}
/**
* padstring.php
*/
function padString($string, $length, $side = "right", $pad = " ") {
if (strlen($string) == $length) { return $string;
} else {
$charsNeeded = $length - strlen($string); $side == "right" ? ($string = $string . $padding) : ($string = $padding . $string);
return $string;
}
}
/**
* main.php
*/
include('classes.php');
include('input.php');
include('padstring.php');
$company = new Company($input);
$company->printReport();
PD9waHAKIAogLyoqCiAqIGlucHV0LnBocAogKi8KIAokaW5wdXQgPSBbCgkvLyBjb3VudCwgcHJvZmVzc2lvbiwgZ3JhZGUsIFtjaGllZl0KIAoJJ1B1cmNoYXNpbmcnID0+IFsKCQlbOSwgRW1wbG95ZWU6Ok1BTkFHRVIsIDFdLAoJCVszLCBFbXBsb3llZTo6TUFOQUdFUiwgMl0sCgkJWzIsIEVtcGxveWVlOjpNQU5BR0VSLCAzXSwKCQlbMiwgRW1wbG95ZWU6Ok1BUktFVEVSLCAxXSwKCQlbMSwgRW1wbG95ZWU6Ok1BTkFHRVIsIDIsIHRydWVdCgldLAogCgknU2FsZXMnID0+IFsKCQlbMTIsIEVtcGxveWVlOjpNQU5BR0VSLCAxXSwKCQlbNiwgRW1wbG95ZWU6Ok1BUktFVEVSLCAxXSwKCQlbMywgRW1wbG95ZWU6OkFOQUxZU1QsIDFdLAoJCVsyLCBFbXBsb3llZTo6QU5BTFlTVCwgMl0sCgkJWzEsIEVtcGxveWVlOjpNQVJLRVRFUiwgMiwgdHJ1ZV0KCV0sCiAKIAoJJ0FkdmVydGlzaW5nJyA9PiBbCgkJWzE1LCBFbXBsb3llZTo6TUFSS0VURVIsIDFdLAoJCVsxMCwgRW1wbG95ZWU6Ok1BUktFVEVSLCAyXSwKCQlbOCwgRW1wbG95ZWU6Ok1BTkFHRVIsIDFdLAoJCVsyLCBFbXBsb3llZTo6RU5HSU5FRVIsIDFdLAoJCVsxLCBFbXBsb3llZTo6TUFSS0VURVIsIDMsIHRydWVdCgldLAogCiAKCSdMb2dpc3RpY3MnID0+IFsKCQlbMTMsIEVtcGxveWVlOjpNQU5BR0VSLCAxXSwKCQlbNSwgRW1wbG95ZWU6Ok1BTkFHRVIsIDJdLAoJCVs1LCBFbXBsb3llZTo6RU5HSU5FRVIsIDFdLAoJCVsxLCBFbXBsb3llZTo6TUFOQUdFUiwgMSwgdHJ1ZV0KCV0KIApdOwogCiAvKioKICogY2xhc3Nlcy5waHAKICovCgpjbGFzcyBDb21wYW55IHsKCXByb3RlY3RlZCBhcnJheSAkZGVwYXJ0bWVudHM7Cglwcm90ZWN0ZWQgaW50ICRudW1PZkRlcHRzOwoKCXB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdChhcnJheSAkaW5wdXQpIHsKCQkkZGVwYXJ0bWVudHMgPSBbXTsKCQlmb3JlYWNoICgkaW5wdXQgYXMgJGRlcGFydG1lbnQgPT4gJGVtcGxveWVlcykgewoJCQkkZGVwYXJ0bWVudHNbXSA9IG5ldyBEZXBhcnRtZW50KCRkZXBhcnRtZW50LCAkZW1wbG95ZWVzKTsKCQl9CgoJCSR0aGlzLT5kZXBhcnRtZW50cyA9ICRkZXBhcnRtZW50czsKCQkkdGhpcy0+bnVtT2ZEZXB0cyA9IGNvdW50KCRkZXBhcnRtZW50cyk7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldERlcGFydG1lbnRzKCk6IGFycmF5IHsKCQlyZXR1cm4gJHRoaXMtPmRlcGFydG1lbnRzOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRUb3RhbFN0YWZmKCk6IGludCB7CgkJJHN0YWZmID0gMDsKCQlmb3JlYWNoICgkdGhpcy0+ZGVwYXJ0bWVudHMgYXMgJGRlcHQpIHsKCQkJJHN0YWZmICs9ICRkZXB0LT5nZXRTdGFmZk51bWJlcigpOwoJCX0KCQlyZXR1cm4gJHN0YWZmOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRUb3RhbExhYm9yQ29zdCgpIHsKCQkkY29zdCA9IDA7CgkJZm9yZWFjaCAoJHRoaXMtPmRlcGFydG1lbnRzIGFzICRkZXB0KSB7CgkJCSRjb3N0ICs9ICRkZXB0LT5nZXRMYWJvckNvc3QoKTsKCQl9CgkJcmV0dXJuICRjb3N0OwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRUb3RhbENvZmZlZURydW5rKCkgewoJCSRhbW91bnQgPSAwOwoJCWZvcmVhY2ggKCR0aGlzLT5kZXBhcnRtZW50cyBhcyAkZGVwdCkgewoJCQkkYW1vdW50ICs9ICRkZXB0LT5nZXRDb2ZmZWVEcnVuaygpOwoJCX0KCQlyZXR1cm4gJGFtb3VudDsKCX0KCglwdWJsaWMgZnVuY3Rpb24gZ2V0VG90YWxQYWdlc1Byb2R1Y2VkKCk6IGludCB7CgkJJHBhZ2VzID0gMDsKCQlmb3JlYWNoICgkdGhpcy0+ZGVwYXJ0bWVudHMgYXMgJGRlcHQpIHsKCQkJJHBhZ2VzICs9ICRkZXB0LT5nZXRQYWdlc1Byb2R1Y2VkKCk7CgkJfQoJCXJldHVybiAkcGFnZXM7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldFRvdGFsQ29zdFBlclBhZ2UoKSB7CgkJJGNvc3QgPSAwOwoJCWZvcmVhY2ggKCR0aGlzLT5kZXBhcnRtZW50cyBhcyAkZGVwdCkgewoJCQkkY29zdCArPSAkZGVwdC0+Z2V0Q29zdFBlclBhZ2UoKTsKCQl9CgkJcmV0dXJuICRjb3N0OwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRBdmVyYWdlU3RhZmYoKSB7CgkJJHN0YWZmID0gMDsKCQlmb3JlYWNoICgkdGhpcy0+ZGVwYXJ0bWVudHMgYXMgJGRlcHQpIHsKCQkJJHN0YWZmICs9ICRkZXB0LT5nZXRTdGFmZk51bWJlcigpOwoJCX0KCQlyZXR1cm4gJHN0YWZmIC8gJHRoaXMtPm51bU9mRGVwdHM7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldEF2ZXJhZ2VMYWJvckNvc3QoKSB7CgkJJGNvc3QgPSAwOwoJCWZvcmVhY2ggKCR0aGlzLT5kZXBhcnRtZW50cyBhcyAkZGVwdCkgewoJCQkkY29zdCArPSAkZGVwdC0+Z2V0TGFib3JDb3N0KCk7CgkJfQoJCXJldHVybiAkY29zdCAvICR0aGlzLT5udW1PZkRlcHRzOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRBdmVyYWdlQ29mZmVlRHJ1bmsoKSB7CgkJJGFtb3VudCA9IDA7CgkJZm9yZWFjaCAoJHRoaXMtPmRlcGFydG1lbnRzIGFzICRkZXB0KSB7CgkJCSRhbW91bnQgKz0gJGRlcHQtPmdldENvZmZlZURydW5rKCk7CgkJfQoJCXJldHVybiAkYW1vdW50IC8gJHRoaXMtPm51bU9mRGVwdHM7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldEF2ZXJhZ2VQYWdlc1Byb2R1Y2VkKCkgewoJCSRwYWdlcyA9IDA7CgkJZm9yZWFjaCAoJHRoaXMtPmRlcGFydG1lbnRzIGFzICRkZXB0KSB7CgkJCSRwYWdlcyArPSAkZGVwdC0+Z2V0UGFnZXNQcm9kdWNlZCgpOwoJCX0KCQlyZXR1cm4gJHBhZ2VzIC8gJHRoaXMtPm51bU9mRGVwdHM7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldEF2ZXJhZ2VDb3N0UGVyUGFnZSgpIHsKCQkkY29zdCA9IDA7CgkJZm9yZWFjaCAoJHRoaXMtPmRlcGFydG1lbnRzIGFzICRkZXB0KSB7CgkJCSRjb3N0ICs9ICRkZXB0LT5nZXRDb3N0UGVyUGFnZSgpOwoJCX0KCQlyZXR1cm4gJGNvc3QgLyAkdGhpcy0+bnVtT2ZEZXB0czsKCX0KCglwdWJsaWMgZnVuY3Rpb24gcHJpbnRSZXBvcnQoKSB7CgkJJGZpcnN0Q29sID0gMjA7CgkJJHJlZ0NvbCA9IDE1OwoKCQllY2hvIHBhZFN0cmluZygnREVQQVJUTUVOVCcsICRmaXJzdENvbCkgLiBwYWRTdHJpbmcoJ1NUQUZGJywgJHJlZ0NvbCwgJ2xlZnQnKSAuIHBhZFN0cmluZygnTEFCT1IgQ09TVCcsICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJ0NPRkZFRSBEUlVOSycsICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJ1BBR0VTJywgJHJlZ0NvbCwgJ2xlZnQnKSAuIHBhZFN0cmluZygnQ09TVCBQRVIgUEFHRScsICRyZWdDb2wsICdsZWZ0JykgLiAiXG4iOwoJCWVjaG8gcGFkU3RyaW5nKCc9JywgJGZpcnN0Q29sLCAncmlnaHQnLCAnPScpIC4gcGFkU3RyaW5nKCc9JywgJHJlZ0NvbCwgJ2xlZnQnLCAnPScpIC4gcGFkU3RyaW5nKCc9JywgJHJlZ0NvbCwgJ2xlZnQnLCAnPScpIC4gcGFkU3RyaW5nKCc9JywgJHJlZ0NvbCwgJ2xlZnQnLCAnPScpIC4gcGFkU3RyaW5nKCc9JywgJHJlZ0NvbCwgJ2xlZnQnLCAnPScpIC4gcGFkU3RyaW5nKCc9JywgJHJlZ0NvbCwgJ2xlZnQnLCAnPScpIC4gIlxuIjsKCgkJZm9yZWFjaCAoJHRoaXMtPmdldERlcGFydG1lbnRzKCkgYXMgJGRlcGFydG1lbnQpIHsKCQkJZWNobyBwYWRTdHJpbmcoJGRlcGFydG1lbnQtPmdldERlcHROYW1lKCksICRmaXJzdENvbCkgLiBwYWRTdHJpbmcoJGRlcGFydG1lbnQtPmdldFN0YWZmTnVtYmVyKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJGRlcGFydG1lbnQtPmdldExhYm9yQ29zdCgpLCAkcmVnQ29sLCAnbGVmdCcpIC4gcGFkU3RyaW5nKCRkZXBhcnRtZW50LT5nZXRDb2ZmZWVEcnVuaygpLCAkcmVnQ29sLCAnbGVmdCcpIC4gcGFkU3RyaW5nKCRkZXBhcnRtZW50LT5nZXRQYWdlc1Byb2R1Y2VkKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJGRlcGFydG1lbnQtPmdldENvc3RQZXJQYWdlKCksICRyZWdDb2wsICdsZWZ0JykgLiAiXG4iOwoJCX0KCgkJZWNobyBwYWRTdHJpbmcoJz0nLCAkZmlyc3RDb2wsICdyaWdodCcsICc9JykgLiBwYWRTdHJpbmcoJz0nLCAkcmVnQ29sLCAnbGVmdCcsICc9JykgLiBwYWRTdHJpbmcoJz0nLCAkcmVnQ29sLCAnbGVmdCcsICc9JykgLiBwYWRTdHJpbmcoJz0nLCAkcmVnQ29sLCAnbGVmdCcsICc9JykgLiBwYWRTdHJpbmcoJz0nLCAkcmVnQ29sLCAnbGVmdCcsICc9JykgLiBwYWRTdHJpbmcoJz0nLCAkcmVnQ29sLCAnbGVmdCcsICc9JykgLiAiXG4iOwoKCQllY2hvIHBhZFN0cmluZygnVE9UQUwnLCAkZmlyc3RDb2wpIC4gcGFkU3RyaW5nKCR0aGlzLT5nZXRUb3RhbFN0YWZmKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldFRvdGFsTGFib3JDb3N0KCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldFRvdGFsQ29mZmVlRHJ1bmsoKSwgJHJlZ0NvbCwgJ2xlZnQnKSAuIHBhZFN0cmluZygkdGhpcy0+Z2V0VG90YWxQYWdlc1Byb2R1Y2VkKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldFRvdGFsQ29zdFBlclBhZ2UoKSwgJHJlZ0NvbCwgJ2xlZnQnKSAuICJcbiI7CgoJCWVjaG8gcGFkU3RyaW5nKCdBVkVSQUdFJywgJGZpcnN0Q29sKSAuIHBhZFN0cmluZygkdGhpcy0+Z2V0QXZlcmFnZVN0YWZmKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldEF2ZXJhZ2VMYWJvckNvc3QoKSwgJHJlZ0NvbCwgJ2xlZnQnKSAuIHBhZFN0cmluZygkdGhpcy0+Z2V0QXZlcmFnZUNvZmZlZURydW5rKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldEF2ZXJhZ2VQYWdlc1Byb2R1Y2VkKCksICRyZWdDb2wsICdsZWZ0JykgLiBwYWRTdHJpbmcoJHRoaXMtPmdldEF2ZXJhZ2VDb3N0UGVyUGFnZSgpLCAkcmVnQ29sLCAnbGVmdCcpIC4gIlxuIjsKCX0KfQoKY2xhc3MgRGVwYXJ0bWVudCB7Cglwcm90ZWN0ZWQgc3RyaW5nICRuYW1lOwoJcHJvdGVjdGVkIGFycmF5ICRzdGFmZjsKCglwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3Qoc3RyaW5nICRuYW1lLCBhcnJheSAkZW1wbG95ZWVzKSB7CgkJJHRoaXMtPm5hbWUgPSAkbmFtZTsKCQkkdGhpcy0+c3RhZmYgPSBbXTsKCQlmb3JlYWNoICgkZW1wbG95ZWVzIGFzICRlbXBHcm91cCkgewoJCQkkZW1wUXVhbnRpdHkgPSAkZW1wR3JvdXBbMF07CgkJCSRlbXBUeXBlID0gJGVtcEdyb3VwWzFdOwoJCQkkZW1wR3JhZGUgPSAkZW1wR3JvdXBbMl07IC8vIDEKCQkJJGVtcENoaWVmID0gaXNzZXQoJGVtcEdyb3VwWzNdKSA/IHRydWUgOiBmYWxzZTsKCQkJZm9yICgkYyA9IDA7ICRjIDwgJGVtcFF1YW50aXR5OyAkYysrKSB7CgkJCQkkdGhpcy0+c3RhZmZbXSA9IG5ldyAkZW1wVHlwZSgkZW1wR3JhZGUsICRlbXBDaGllZik7CgkJCX0KCQl9Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldERlcHROYW1lKCk6IHN0cmluZyB7CgkJcmV0dXJuICR0aGlzLT5uYW1lOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRTdGFmZk51bWJlcigpOiBpbnQgewoJCSRzdGFmZk51bWJlciA9IGNvdW50KCR0aGlzLT5zdGFmZik7CgkJcmV0dXJuICRzdGFmZk51bWJlcjsKCX0KCglwdWJsaWMgZnVuY3Rpb24gZ2V0TGFib3JDb3N0KCk6IGludCB7CgkJJGFnZ3JlZ2F0ZUNvc3QgPSAwOwoJCWZvcmVhY2ggKCR0aGlzLT5zdGFmZiBhcyAkZW1wbG95ZWUpIHsKCQkJJGFnZ3JlZ2F0ZUNvc3QgKz0gJGVtcGxveWVlLT5nZXRBY3R1YWxQYXkoKTsKCQl9CgkJcmV0dXJuICRhZ2dyZWdhdGVDb3N0OwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRDb2ZmZWVEcnVuaygpOiBpbnQgewoJCSR0b3RhbENvZmZlZURydW5rID0gMDsKCQlmb3JlYWNoICgkdGhpcy0+c3RhZmYgYXMgJGVtcGxveWVlKSB7CgkJCSR0b3RhbENvZmZlZURydW5rICs9ICRlbXBsb3llZS0+Z2V0QWN0dWFsQ29mZmVlQ29uc3VtcHRpb24oKTsKCQl9CgkJcmV0dXJuICR0b3RhbENvZmZlZURydW5rOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRQYWdlc1Byb2R1Y2VkKCkgewoJCSR0b3RhbFBhZ2VzUHJvZHVjZWQgPSAwOwoJCWZvcmVhY2ggKCR0aGlzLT5zdGFmZiBhcyAkZW1wbG95ZWUpIHsKCQkJJHRvdGFsUGFnZXNQcm9kdWNlZCArPSAkZW1wbG95ZWUtPmdldEFjdHVhbFBhcGVyd29ya1Byb2R1Y2VkKCk7CgkJfQoJCXJldHVybiAkdG90YWxQYWdlc1Byb2R1Y2VkOwoJfQoKCXB1YmxpYyBmdW5jdGlvbiBnZXRDb3N0UGVyUGFnZSgpIHsKCQkkcGFnZXMgPSAkdGhpcy0+Z2V0UGFnZXNQcm9kdWNlZCgpOwoJCSRsYWJvckNvc3QgPSAkdGhpcy0+Z2V0TGFib3JDb3N0KCk7CgkJcmV0dXJuIHJvdW5kKCRsYWJvckNvc3QgLyAkcGFnZXMsIDIpOwoJfQp9CgphYnN0cmFjdCBjbGFzcyBFbXBsb3llZSB7Cgljb25zdCBNQU5BR0VSID0gIk1hbmFnZXIiOwoJY29uc3QgTUFSS0VURVIgPSAiTWFya2V0ZXIiOwoJY29uc3QgRU5HSU5FRVIgPSAiRW5naW5lZXIiOwoJY29uc3QgQU5BTFlTVCA9ICJBbmFseXN0IjsKCglwcm90ZWN0ZWQgaW50ICRncmFkZTsKCXByb3RlY3RlZCAkYmFzZVJhdGU7Cglwcm90ZWN0ZWQgYm9vbCAkY2hpZWY7Cglwcm90ZWN0ZWQgJGJhc2VDb2ZmZWVDb25zdW1wdGlvbjsKCXByb3RlY3RlZCBpbnQgJGJhc2VQYXBlcndvcmtQcm9kdWNlZDsKCglwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoaW50ICRncmFkZSwgYm9vbCAkY2hpZWYgPSBmYWxzZSkgewoJCSR0aGlzLT5ncmFkZSA9ICRncmFkZTsKCQkkdGhpcy0+Y2hpZWYgPSAkY2hpZWY7Cgl9CgoJcHVibGljIGZ1bmN0aW9uIGdldEFjdHVhbFBheSgpIHsKCQkkcmF0ZSA9ICR0aGlzLT5iYXNlUmF0ZTsKCQlpZiAoJHRoaXMtPmdyYWRlID09IDIpIHsKCQkJJHJhdGUgKj0gMS4yNTsKCQl9IGVsc2VpZiAoJHRoaXMtPmdyYWRlID09IDMpIHsKCQkJJHJhdGUgPSAkcmF0ZSAqIDEuNTsKCQl9CgoJCXJldHVybiAkdGhpcy0+Y2hpZWYgPyAkcmF0ZSAqIDIgOiAkcmF0ZTsKCX0KCglwdWJsaWMgZnVuY3Rpb24gZ2V0QWN0dWFsQ29mZmVlQ29uc3VtcHRpb24oKSB7CgkJcmV0dXJuICR0aGlzLT5jaGllZiA/ICR0aGlzLT5iYXNlQ29mZmVlQ29uc3VtcHRpb24gKiAyIDogJHRoaXMtPmJhc2VDb2ZmZWVDb25zdW1wdGlvbjsKCX0KCglwdWJsaWMgZnVuY3Rpb24gZ2V0QWN0dWFsUGFwZXJ3b3JrUHJvZHVjZWQoKTogaW50IHsKCQlyZXR1cm4gJHRoaXMtPmNoaWVmID8gMCA6ICR0aGlzLT5iYXNlUGFwZXJ3b3JrUHJvZHVjZWQ7CQoJfQp9CgpjbGFzcyBNYW5hZ2VyIGV4dGVuZHMgRW1wbG95ZWUgewoJcHJvdGVjdGVkICRiYXNlUmF0ZSA9IDUwMDsKCXByb3RlY3RlZCAkYmFzZUNvZmZlZUNvbnN1bXB0aW9uID0gMjA7Cglwcm90ZWN0ZWQgaW50ICRiYXNlUGFwZXJ3b3JrUHJvZHVjZWQgPSAyMDA7Cn0KCmNsYXNzIE1hcmtldGVyIGV4dGVuZHMgRW1wbG95ZWUgewoJcHJvdGVjdGVkICRiYXNlUmF0ZSA9IDQwMDsKCXByb3RlY3RlZCAkYmFzZUNvZmZlZUNvbnN1bXB0aW9uID0gMTU7Cglwcm90ZWN0ZWQgaW50ICRiYXNlUGFwZXJ3b3JrUHJvZHVjZWQgPSAxNTA7Cn0KCmNsYXNzIEVuZ2luZWVyIGV4dGVuZHMgRW1wbG95ZWUgewoJcHJvdGVjdGVkICRiYXNlUmF0ZSA9IDIwMDsKCXByb3RlY3RlZCAkYmFzZUNvZmZlZUNvbnN1bXB0aW9uID0gNTsKCXByb3RlY3RlZCBpbnQgJGJhc2VQYXBlcndvcmtQcm9kdWNlZCA9IDUwOwp9CgpjbGFzcyBBbmFseXN0IGV4dGVuZHMgRW1wbG95ZWUgewoJcHJvdGVjdGVkICRiYXNlUmF0ZSA9IDgwMDsKCXByb3RlY3RlZCAkYmFzZUNvZmZlZUNvbnN1bXB0aW9uID0gNTA7Cglwcm90ZWN0ZWQgaW50ICRiYXNlUGFwZXJ3b3JrUHJvZHVjZWQgPSA1Owp9CgogIC8qKgogKiBwYWRzdHJpbmcucGhwCiAqLwogCiBmdW5jdGlvbiBwYWRTdHJpbmcoJHN0cmluZywgJGxlbmd0aCwgJHNpZGUgPSAicmlnaHQiLCAkcGFkID0gIiAiKSB7CglpZiAoc3RybGVuKCRzdHJpbmcpID09ICRsZW5ndGgpIHsKCQlyZXR1cm4gJHN0cmluZzsKCX0gZWxzZSB7CgkJJGNoYXJzTmVlZGVkID0gJGxlbmd0aCAtIHN0cmxlbigkc3RyaW5nKTsKCQkkcGFkZGluZyA9IHN0cl9yZXBlYXQoJHBhZCwgJGNoYXJzTmVlZGVkKTsKCQkkc2lkZSA9PSAicmlnaHQiID8gKCRzdHJpbmcgPSAkc3RyaW5nIC4gJHBhZGRpbmcpIDogKCRzdHJpbmcgPSAkcGFkZGluZyAuICRzdHJpbmcpOwoJCXJldHVybiAkc3RyaW5nOwoJfQp9CiAKIC8qKgogKiBtYWluLnBocAogKi8KIAppbmNsdWRlKCdjbGFzc2VzLnBocCcpOwppbmNsdWRlKCdpbnB1dC5waHAnKTsKaW5jbHVkZSgncGFkc3RyaW5nLnBocCcpOwoKJGNvbXBhbnkgPSBuZXcgQ29tcGFueSgkaW5wdXQpOwoKJGNvbXBhbnktPnByaW50UmVwb3J0KCk7