<?
abstract class Employee
{
    const RANK_FIRST = 1;
    const RANK_SECOND = 2;
    const RANK_THIRD = 3;
    const PROF_MANAGER = 1;
    const PROF_MARKETER = 2;
    const PROF_ENGINEER = 3;
    const PROF_ANALYST = 4;
    
    protected $isLeader = false;
    protected $defaultSalary;
    protected $coffeeConsumption;
    protected $pagesCreated;
    
    public function __construct($rank)
    {
        $this->rank = $rank;
    }
    
    public function createEmployee($profession, $rank)
    {
        switch ($profession) {
            case Employee::PROF_MANAGER:
                $employee = new Manager($rank);
                break;
            case Employee::PROF_MARKETER:
                $employee = new Marketer($rank);
                break;
            case Employee::PROF_ENGINEER:
                $employee = new Engineer($rank);
                break;
            case Employee::PROF_ANALYST:
                $employee = new Analyst($rank);
                break;
            default:
                try {
                    $employee = NULL;
                    throw new Exception("<b>Error:</b> Profession {$profession} is not an Employee derivated class.");
                }
                catch (Exception $e) {
                    echo $e->getMessage();
                }
                break;
        }
        return $employee;
    }
    
    public function getSalary()
    {
        $salaryRate = 1;
        if ($this->rank == Employee::RANK_SECOND) {
            $salaryRate = 1.25;
        } elseif ($this->rank == Employee::RANK_THIRD) {
            $salaryRate = 1.5;
        }
        if ($this->isLeader) {
            $salaryRate *= 1.5;
        }
        return $this->defaultSalary * $salaryRate;
    }
    
    public function getCoffeeConsumption()
    {
        $coffeeConsumption = $this->coffeeConsumption;
        if ($this->isLeader) {
            $coffeeConsumption = $this->coffeeConsumption * 2;
        }
        return $coffeeConsumption;
    }
    
    public function getPagesCreated()
    {
        $pagesCreated = $this->pagesCreated;
        if ($this->isLeader) {
            $pagesCreated = 0;
        }
        return $pagesCreated;
    }
    
    public function setIsLeader($isLeader)
    {
        $this->isLeader = $isLeader;
        return $this;
    }
}

class Manager extends Employee
{
    protected $defaultSalary = 500;
    protected $coffeeConsumption = 20;
    protected $pagesCreated = 200;
}

class Marketer extends Employee
{
    protected $defaultSalary = 400;
    protected $coffeeConsumption = 15;
    protected $pagesCreated = 150;
}

class Engineer extends Employee
{
    protected $defaultSalary = 200;
    protected $coffeeConsumption = 5;
    protected $pagesCreated = 50;
}

class Analyst extends Employee
{
    protected $defaultSalary = 800;
    protected $coffeeConsumption = 50;
    protected $pagesCreated = 5;
}

class Department
{
    protected $name;
    protected $employees = array();
    protected $leader;
    
    public function __construct($name)
    {
        $this->name = $name;
    }
    
    public function addEmployees($profession, $rank, $count = 1)
    {
        for ($i = 0; $i < $count; $i++) {
            $this->employees[] = Employee::createEmployee($profession, $rank);
        }
        return $this;
    }
    
    public function setLeader(Employee $person)
    {
        $person->setIsLeader(true);
        $this->leader = $person;
    }
    
    public function getTotalSalary()
    {
        $totalSalary = 0;
        foreach ($this->employees as $employee) {
            $totalSalary += $employee->getSalary();
        }
        return $totalSalary;
    }
    
    public function getTotalPages()
    {
        $totalPages = 0;
        foreach ($this->employees as $employee) {
            $totalPages += $employee->getPagesCreated();
        }
        return $totalPages;
    }
    
    public function getTotalCoffeeConsumption()
    {
        $totalCoffee = 0;
        foreach ($this->employees as $employee) {
            $totalCoffee += $employee->getCoffeeConsumption();
        }
        return $totalCoffee;
    }
    
    public function getEmployeesCount()
    {
        return count($this->employees);
    }
    
    public function getCurrencyPerPage()
    {
        $currencyPerPage = $this->getTotalSalary() / $this->getTotalPages();
        return $currencyPerPage;
    }
    public function getDepartmentSummary()
    {
        $format = "%-15s %15d %15d %15d %15d %15.2f\n";
        printf($format, $this->name, $this->getEmployeesCount(), $this->getTotalSalary(), $this->getTotalCoffeeConsumption(), $this->getTotalPages(), $this->getCurrencyPerPage());
    }
}

$salesDepartment = new Department("Продаж");
$salesDepartment->addEmployees(Employee::PROF_MANAGER, Employee::RANK_FIRST, 12)->addEmployees(Employee::PROF_MARKETER, Employee::RANK_FIRST, 6)->addEmployees(Employee::PROF_ANALYST, Employee::RANK_FIRST, 3)->addEmployees(Employee::PROF_ANALYST, Employee::RANK_SECOND, 2);
$salesDepartment->setLeader(new Manager(Employee::RANK_SECOND));

$purchasesDepartment = new Department("Закупок");
$purchasesDepartment->addEmployees(Employee::PROF_MANAGER, Employee::RANK_FIRST, 9)->addEmployees(Employee::PROF_MANAGER, Employee::RANK_SECOND, 3)->addEmployees(Employee::PROF_MANAGER, Employee::RANK_THIRD, 2)->addEmployees(Employee::PROF_MARKETER, Employee::RANK_FIRST, 2);
$purchasesDepartment->setLeader(new Marketer(Employee::RANK_SECOND));

$advertisementDepartment = new Department("Рекламы");
$advertisementDepartment->addEmployees(Employee::PROF_MARKETER, Employee::RANK_FIRST, 15)->addEmployees(Employee::PROF_MARKETER, Employee::RANK_SECOND, 10)->addEmployees(Employee::PROF_MANAGER, Employee::RANK_FIRST, 8)->addEmployees(Employee::PROF_ENGINEER, Employee::RANK_FIRST, 2);
$advertisementDepartment->setLeader(new Marketer(Employee::RANK_THIRD));

$logisticsDepartment = new Department("Логистики");
$logisticsDepartment->addEmployees(Employee::PROF_MANAGER, Employee::RANK_FIRST, 13)->addEmployees(Employee::PROF_MANAGER, Employee::RANK_SECOND, 5)->addEmployees(Employee::PROF_ENGINEER, Employee::RANK_FIRST, 5);
$logisticsDepartment->setLeader(new Manager(Employee::RANK_FIRST));

$departmentsArray   = array(
    'salesDepartment',
    'purchasesDepartment',
    'advertisementDepartment',
    'logisticsDepartment'
);
$countofDepartments = count($departmentsArray);
$totalEmployees     = 0;
$totalSalary        = 0;
$totalCoffee        = 0;
$totalPages         = 0;
$currencyPerPage    = 0;
printf("%-15s %16s %19s %19s %19s %22s\n", 'Департамент', 'cотр.', 'тугр.', 'кофе', 'стр.', 'тугр./стр.');
printf("%'-90s\n", '');
foreach ($departmentsArray as $department) {
    $$department->getDepartmentSummary();
    $totalEmployees += $$department->getEmployeesCount();
    $totalSalary += $$department->getTotalSalary();
    $totalCoffee += $$department->getTotalCoffeeConsumption();
    $totalPages += $$department->getTotalPages();
    $currencyPerPage += $$department->getCurrencyPerPage();
}
#$avgEmployees = $totalEmployees/$countofDepartments;
#$avgSalary = $totalSalary/$countofDepartments;
#$avgCoffee = $totalCoffee/$countofDepartments;
#$avgPages = $totalPages/$countofDepartments;
#$avgCurrencyPerPage = $currencyPerPage/$countofDepartments;
$parametersArray = array('totalEmployees'=>'avgEmployees', 'totalSalary'=>'avgSalary', 'totalCoffee'=>'avgCoffee', 'totalPages'=>'avgPages', 'currencyPerPage'=>'avgCurrencyPerPage');
foreach($parametersArray as $totalVariable => $avgVariable){
    $$avgVariable = $$totalVariable / $countofDepartments;
}
printf("%-15s %15d %15d %15d %15d %15.2f\n", 'Среднее', $avgEmployees, $avgSalary, $avgCoffee, $avgPages, $avgCurrencyPerPage);
printf("%-15s %15d %15d %15d %15d %15.2f\n", 'Всего', $totalEmployees, $totalSalary, $totalCoffee, $totalPages, $currencyPerPage);
#Employee::createEmployee('Driver', Employee::RANK_FIRST);
?>