<?php
 
declare(strict_types=1);
 
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
    {
        $amount = 0;
        foreach ($this->Employees as $profEmp) {
            $amount += $profEmp->NumberOfEmp;
        }
        return $amount;
    }
 
    #Суммарные выплаты зарплат по отделу
    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 $NumberOfEmp;
    public $rank; // Ранг работника
    public $isTheHead = false; // Является ли работник руководителем
 
    public $rankCoeff = [1, 1.25, 1.5]; // Множитель ставки в зависимости от ранга
    public $monthlyTariffRate; // Месячная ставка
    public $defaultCoffee; // Сколько выпивает кофе
    public $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 $this->NumberOfEmp * $headCoeff * $this->rankCoeff[0] * $this->monthlyTariffRate;
            case 2:
                return $this->NumberOfEmp * $headCoeff * $this->rankCoeff[1] * $this->monthlyTariffRate;
            case 3:
                return $this->NumberOfEmp * $headCoeff * $this->rankCoeff[2] * $this->monthlyTariffRate;
        }
    }
 
    public function coffee()
    {
        if ($this->isTheHead) {
            $coffee = 0;
        } else {
            $coffee = $this->defaultCoffee;
        }
        return $this->NumberOfEmp * $coffee;
    }
 
    public function reportPages()
    {
        if ($this->isTheHead) {
            $reportPages = 0;
        } else {
            $reportPages = $this->defaultReportPages;
        }
        return $this->NumberOfEmp * $reportPages;
    }
 
}
 
class Managers extends Employee
{
 
    public $monthlyTariffRate = 500;
    public $defaultCoffee = 20;
    public $defaultReportPages = 200;
 
}
 
class Marketers extends Employee
{
    public $monthlyTariffRate = 400;
    public $defaultCoffee = 15;
    public $defaultReportPages = 150;
 
}
 
class Engineers extends Employee
{
    public $monthlyTariffRate = 200;
    public $defaultCoffee = 5;
    public $defaultReportPages = 50;
 
}
 
class Analysts extends Employee
{
    public $monthlyTariffRate = 800;
    public $defaultCoffee = 50;
    public $defaultReportPages = 5;
 
}
 
# Департамент закупок. Создание работников
# 9×ме1
$purchMe1 = new Managers (1);
$purchMe1->NumberOfEmp = 9; // Теперь пересчеты всех свойств деньги кофе и так далее, буду зависит от этого свойства
 
# 3×ме2
$purchMe2 = new Managers(2);
$purchMe2->NumberOfEmp = 3;
 
#2×ме3
$purchMe3 = new Managers(3);
$purchMe3->NumberOfEmp = 2;
 
#2×ма1
$purchMa1 = new Marketers(1);
$purchMa1->NumberOfEmp = 2;
 
# Руководитель департамента ме2
$purchHeadMa1 = new Managers(2,true);
$purchHeadMa1->NumberOfEmp = 1;
 
# Массив работников для департамента закупок
$purchEmp = [$purchMe1,$purchMe2,$purchMe3,$purchMa1,$purchHeadMa1];
 
#Создаём департамент заукпок
$purchasing = new Department;
$purchasing->name = 'Закупок';
$purchasing->Employees = $purchEmp;
 
# Все объекты департаментов кладём в массив
$departments = [$purchasing];
 
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);