<?php
declare(strict_types=1);
 
    // Не выбрасываем исключение если ошибка подавлена с
    // помощью оператора @
        return;
    }
 
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});
 
class Company
{
    public $departments;
 
    # Кол-во сотрудников всей компании
    public function companyEmployees(): float
    {
        $companyEmp = 0;
        foreach ($this->departments as $department) {
            $companyEmp += $department->departmentEmp();
        }
        return $companyEmp;
    }
 
    # Кол-во сотрудников в среднем на департамент
    public function companyEmployeesAverage(): float
    {
        return round($this->companyEmployees() / count($this->departments), 2);     }
 
    #Денёжные выплаты по всей компании
    public function companySalary(): float
    {
        $companySal = 0;
        foreach ($this->departments as $department) {
            $companySal += $department->departmentSalary();
        }
        return $companySal;
    }
 
    # Денёжные выплаты в среднем на департамент
    public function companySalaryAverage(): float
    {
        return round($this->companySalary() / count($this->departments), 2);     }
 
    # Кол-во выпитового кофе по компании
    public function companyCoffee(): float
    {
        $companyECof = 0;
        foreach ($this->departments as $department) {
            $companyECof += $department->departmentCoffee();
        }
        return $companyECof;
    }
 
    # Кофе в среднем на департамент
    public function companyCoffeeAverage(): float
    {
        return round($this->companyCoffee() / count($this->departments), 2);     }
 
    # Кол-во страниц документов по компании
    public function companyPages(): float
    {
        $companyPag = 0;
        foreach ($this->departments as $department) {
            $companyPag += $department->departmentPages();
        }
        return $companyPag;
    }
 
    # Кол-во страниц в среднем на департамент
    public function companyPagesAverage(): float
    {
        return round($this->companyPages() / count($this->departments), 2);     }
 
    # Сумма ден. ед. за страницу по компании
    public function companyPagePrice(): float
    {
        $companyPagPr = 0;
        foreach ($this->departments as $department) {
            $companyPagPr += $department->pagePrice();
        }
        return $companyPagPr;
    }
 
    # Среднея стоимость страницы по компании
    public function companyPagePriceAverage(): float
    {
        return round($this->companyPagePrice() / count($this->departments), 2);     }
}
 
class Department
{
    public $name;
    public $Employees;
 
    #Кол-во сотрудников в отделе
    public function departmentEmp(): int
    {
        return count($this->Employees);     }
 
    #Суммарные выплаты зарплат по отделу
    public function departmentSalary(): float
    {
        $departmentSalary = 0;
        foreach ($this->Employees as $employee) {
            $departmentSalary += $employee->salary();
        }
        return $departmentSalary;
    }
 
    #Суммарно выпитое кофе в отделе
    public function departmentCoffee(): float
    {
        $departmentCoffee = 0;
        foreach ($this->Employees as $employee) {
            $departmentCoffee += $employee->coffee();
        }
        return $departmentCoffee;
    }
 
    # Суммарное количество документов в отделе
    public function departmentPages(): float
    {
        $departmentPages = 0;
        foreach ($this->Employees as $employee) {
            $departmentPages += $employee->reportPages();
        }
        return $departmentPages;
    }
 
    # Ден. ед. за страницу по отделу
    public function pagePrice(): float
    {
        return round($this->departmentSalary() / $this->departmentPages(), 2);     }
 
}
 
abstract class Employee
{
 
    public $rank; // Ранг работника
    public $isTheHead = false; // Является ли работник руководителем
    private $rankCoeff = [1, 1.25, 1.5]; // Множитель ставки в зависимости от ранга
    protected $monthlyTariffRate; // Месячная ставка
    protected $defaultCoffee; // Сколько выпивает кофе
    protected $defaultReportPages; // Сколько делает страниц документов
 
    public function __construct($rank, $isTheHead = false)
    {
        $this->rank = $rank;
        $this->isTheHead = $isTheHead;
    }
 
    # Деньги, которые получает работник
    public function salary(): float
    {
        $headCoeff = 1;
        if ($this->isTheHead) {
            $headCoeff = 1.5;
        }
 
        switch ($this->rank) {
            case 1:
                return $headCoeff * $this->rankCoeff[0] * $this->monthlyTariffRate;
            case 2:
                return $headCoeff * $this->rankCoeff[1] * $this->monthlyTariffRate;
            case 3:
                return $headCoeff * $this->rankCoeff[2] * $this->monthlyTariffRate;
        }
    }
 
    public function coffee()
    {
        if ($this->isTheHead) {
            $coffee = 0;
        } else {
            $coffee = $this->defaultCoffee;
        }
        return $coffee;
    }
 
    public function reportPages()
    {
        if ($this->isTheHead) {
            $reportPages = 0;
        } else {
            $reportPages = $this->defaultReportPages;
        }
        return $reportPages;
    }
 
}
 
class Manager extends Employee
{
    protected $monthlyTariffRate = 500;
    protected $defaultCoffee = 20;
    protected $defaultReportPages = 200;
 
}
 
class Marketer extends Employee
{
    protected $monthlyTariffRate = 400;
    protected $defaultCoffee = 15;
    protected $defaultReportPages = 150;
 
}
 
class Engineer extends Employee
{
    protected $monthlyTariffRate = 200;
    protected $defaultCoffee = 5;
    protected $defaultReportPages = 50;
 
}
 
class Analyst extends Employee
{
    protected $monthlyTariffRate = 800;
    protected $defaultCoffee = 50;
    protected $defaultReportPages = 5;
 
}
 
 
# Департамент закупок. Создание работников
# 9×ме1
$me1 = new Manager(1);
$me2 = new Manager(1);
$me3 = new Manager(1);
$me4 = new Manager(1);
$me5 = new Manager(1);
$me6 = new Manager(1);
$me7 = new Manager(1);
$me8 = new Manager(1);
$me9 = new Manager(1);
 
# 3×ме2
$me10 = new Manager(2);
$me11 = new Manager(2);
$me12 = new Manager(2);
#2×ме3
$me13 = new Manager(3);
$me14 = new Manager(3);
 
#2×ма1
$ma1 = new Marketer(1);
$ma2 = new Marketer(1);
 
# Руководитель департамента ме2
$me15 = new Manager(2, true);
 
# Массив работников для департамента закупок
$purchEmp = [$me1, $me2, $me3, $me4, $me5, $me6, $me7, $me8, $me9, $me10, $me11, $me12, $me13, $me14, $ma1, $ma2, $me15];
 
# Создаём отел закупок
$purchasing = new Department;
$purchasing->name = 'Закупок';
$purchasing->Employees = $purchEmp;
 
# Департамент продаж. Создание работников
#12×ме1
for ($i = 0; $i < 12; $i += 1) {
    $salesEmp[] = new Manager(1);
}
 
# 6×ма1
for ($i = 0; $i < 6; $i += 1) {
    $salesEmp[] = new Marketer(1);
}
 
# 3×ан1
for ($i = 0; $i < 3; $i += 1) {
    $salesEmp[] = new Analyst(1);
}
 
# 2×ан2
for ($i = 0; $i < 2; $i += 1) {
    $salesEmp[] = new Analyst(2);
}
 
#руководитель ма2
for ($i = 0; $i < 1; $i += 1) {
    $salesEmp[] = new Marketer(2, true);
}
 
 
#Создаём отдел продаж
$sales = new Department;
$sales->name = 'Продаж';
$sales->Employees = $salesEmp;
 
# Департамент рекламы. Создание работников
#15×ма1
for ($i = 0; $i < 15; $i += 1) {
    $advertisingEmp[] = new Manager(1);
}
 
#10×ма2
for ($i = 0; $i < 10; $i += 1) {
    $advertisingEmp[] = new Manager(2);
}
 
#8×ме1
for ($i = 0; $i < 8; $i += 1) {
    $advertisingEmp[] = new Marketer(1);
}
 
#2×ин1
for ($i = 0; $i < 2; $i += 1) {
    $advertisingEmp[] = new Engineer(1);
}
 
#руководитель ма3
for ($i = 0; $i < 1; $i += 1) {
    $advertisingEmp[] = new Manager(3, true);
}
 
#Создание департамента рекламы
$advertising = new Department;
$advertising->name = 'Рекламы';
$advertising->Employees = $advertisingEmp;
 
# Департамент логистики. Создание работников
#13×ме1
for ($i = 0; $i < 13; $i += 1) {
    $logisticsEmp[] = new Manager(1);
}
 
#5×ме2
for ($i = 0; $i < 5; $i += 1) {
    $logisticsEmp[] = new Manager(2);
}
 
#5×ин1
for ($i = 0; $i < 5; $i += 1) {
    $logisticsEmp[] = new Engineer(1);
}
 
#руководитель ме1
for ($i = 0; $i < 1; $i += 1) {
    $logisticsEmp[] = new Manager(1, true);
}
 
# Создание департамента логистики
$logistics = new Department;
$logistics->name = 'Логистики';
$logistics->Employees = $logisticsEmp;
 
# Все объекты департаментов кладём в массив
$departments = [$purchasing, $sales, $advertising, $logistics];
 
function padRight($string, int $length): string
{
    $string = (string)$string;
    return $string;
 
}
 
function padLeft($string, int $length): string
{
    $string = (string)$string;
    return $string;
}
 
 
# Создание таблички
echo padRight('Департамент', 11) .
    padLeft('сотр.', 11) .
    padLeft('тугр.', 11) .
    padLeft('кофе', 11) .
    padLeft('стр.', 11) .
    padLeft('тугр./стр.', 16) .
    PHP_EOL .
    PHP_EOL;
 
foreach ($departments as $department) {
    echo padRight($department->name, 11) .
        padLeft($department->departmentEmp(), 11) .
        padLeft($department->departmentSalary(), 11) .
        padLeft($department->departmentCoffee(), 11) .
        padLeft($department->departmentPages(), 11) .
        padLeft($department->pagePrice(), 16) .
        PHP_EOL;
}
 
# Создаём компанию
$company1 = new Company;
$company1->departments = $departments;
 
# Строки 'всего', 'среднее' итоговые цифры по всей компании
    PHP_EOL .
    padRight('Всего', 11) .
    padLeft($company1->companyEmployees(), 11) .
    padLeft($company1->companySalary(), 11) .
    padLeft($company1->companyCoffee(), 11) .
    padLeft($company1->companyPages(), 11) .
    padLeft('-', 16) .
    PHP_EOL;
 
echo padRight('Среднее', 11) .
    padLeft($company1->companyEmployeesAverage(), 11) .
    padLeft($company1->companySalaryAverage(), 11) .
    padLeft($company1->companyCoffeeAverage(), 11) .
    padLeft($company1->companyPagesAverage(), 11) .
    padLeft($company1->companyPagePriceAverage(), 16);