<?php

mb_internal_encoding('UTF-8');

abstract class Employee
{
    public $rank;
    public $isChief = false;
    public $baseRate;
    public $coffeeConsumption;
    public $paperConsumption;

    public function __construct($rank = 1)
    {
        $this->rank = $rank;
    }
    public function getSalary()
    {
        $salary = $this->baseRate;
        if ($this->rank == 2) {
            $salary *= 1.25;
        } elseif ($this->rank == 3) {
            $salary *= 1.5;
        }
        if ($this->isChief) {
            $salary *= 1.5;
        }
        return $salary;
    }
    public function getCoffeeConsumption(){
        if ($this->isChief) {
            return $this->coffeeConsumption * 2;
        } else {
            return $this->coffeeConsumption;
        }
    }
    public function getPaperConsumption()
    {
        if ($this->isChief) {
            return 0;
        } else {
            return $this->paperConsumption;
        }
    }
}

class Manager extends Employee
{
    public $baseRate = 500;
    public $coffeeConsumption = 20;
    public $paperConsumption = 200;
}

class Marketing extends Employee
{
    public $baseRate = 400;
    public $coffeeConsumption = 15;
    public $paperConsumption = 150;
}

class Engineer extends Employee
{
    public $baseRate = 200;
    public $coffeeConsumption = 5;
    public $paperConsumption = 50;
}

class Analyst extends Employee
{
    public $baseRate = 800;
    public $coffeeConsumption = 50;
    public $paperConsumption = 5;
}

class Department
{
    public $name;
    public $chief;
    public $employees;

    public function __construct ($name)
    {
        $this->name = $name;
    }

    public function setChief(Employee $chief)
    {
        $chief->isChief = true;
        $this->chief = $chief;
    }
    public function addEmployees($employees)
    {
        foreach ($employees as $employee) {
            $this->employees[] = $employee;
        }
    }
    public function getEmployeesCount()
    {
        return count($this->employees) + 1;
    }
    public function getEmployeesSalary()
    {
        $employeesSalary = 0;
        foreach ($this->employees as $employee) {
            $employeesSalary += $employee->getSalary();
        }
        $employeesSalary += $this->chief->getSalary();
        return round($employeesSalary);
    }
    public function getConsumptionOfCoffee()
    {
        $consumptionOfCoffee = 0;
        foreach ($this->employees as $employee) {
            $consumptionOfCoffee += $employee->getCoffeeConsumption();
        }
        $consumptionOfCoffee += $this->chief->getCoffeeConsumption();
        return $consumptionOfCoffee;
    }
    public function getPaperConsumption()
    {
        $paperConsumption = 0;
        foreach ($this->employees as $employee) {
            $paperConsumption += $employee->getPaperConsumption();
        }
        $paperConsumption += $this->chief->getPaperConsumption();
        return $paperConsumption;
    }
    public function getCostPerPage()
    {
        return round($this->getEmployeesSalary() / $this->getPaperConsumption(), 2);
    }
}

//Функция генерация $count количества заданных сотрудников
function generateEmployeesList ($name, $rank, $count, $employees)
{
    for ($i = 0; $i < $count; ++$i) {
        $employees[] = new $name($rank);
    }
    return $employees;
}

//Создаем департаменты
$employees = array();
$employees = generateEmployeesList('Manager', 1, 9, $employees);
$employees = generateEmployeesList('Manager', 2, 3, $employees);
$employees = generateEmployeesList('Manager', 3, 2, $employees);
$employees = generateEmployeesList('Marketing', 1, 2, $employees);
$chief = new Manager(2);
$departmentOfProcurement = new Department('Закупок');
$departmentOfProcurement->setChief($chief);
$departmentOfProcurement->addEmployees($employees);

$employees = array();
$employees = generateEmployeesList('Manager', 1, 12, $employees);
$employees = generateEmployeesList('Marketing', 1, 6, $employees);
$employees = generateEmployeesList('Analyst', 1, 3, $employees);
$employees = generateEmployeesList('Analyst', 2, 2, $employees);
$chief = new Marketing(2);
$salesDepartment = new Department('Продаж');
$salesDepartment->setChief($chief);
$salesDepartment->addEmployees($employees);

$employees = array();
$employees = generateEmployeesList('Marketing', 1, 15, $employees);
$employees = generateEmployeesList('Marketing', 2, 10, $employees);
$employees = generateEmployeesList('Manager', 1, 8, $employees);
$employees = generateEmployeesList('Engineer', 1, 2, $employees);
$chief = new Marketing(3);
$departmentOfAdvertising = new Department('Рекламы');
$departmentOfAdvertising->setChief($chief);
$departmentOfAdvertising->addEmployees($employees);

$employees = array();
$employees = generateEmployeesList('Manager', 1, 13, $employees);
$employees = generateEmployeesList('Manager', 2, 5, $employees);
$employees = generateEmployeesList('Engineer', 1, 5, $employees);
$chief = new Manager(1);
$logisticDepartment = new Department('Логистики');
$logisticDepartment->setChief($chief);
$logisticDepartment->addEmployees($employees);

$departments = array ($departmentOfProcurement, $salesDepartment, $departmentOfAdvertising, $logisticDepartment);

//Функции генерирующие отступ для строки слева и справа
function padRight($string, $length)
{
    $spaces = $length - mb_strlen($string);
    if ($spaces >= 0) {
        return $string . str_repeat(' ', $spaces);
    } else {
        return ' ' . mb_substr($string, 0, $length - 2) . '.';
    }
}
function padLeft($string, $length)
{
    $spaces = $length - mb_strlen($string);
    if ($spaces >= 0) {
        return str_repeat(' ', $spaces) . $string;
    } else {
        return ' ' . mb_substr($string, 0, $length - 2) . '.';
    }
}

$columnWidth = 12;

//Заголовок таблицы
echo padRight('Департамент', $columnWidth) .
    padLeft('сотр.', $columnWidth) .
    padLeft('тугр.', $columnWidth) .
    padLeft('кофе', $columnWidth) .
    padLeft('стр.', $columnWidth) .
    padLeft('тугр./стр.', $columnWidth) . "\n";
echo "-------------------------------------------------------------------------\n";

//Таблица
$total = array();
foreach ($departments as $department) {
    $employeesCount = $department->getEmployeesCount();
    $total['employeesCount'][] = $employeesCount;
    $employeesSalary = $department->getEmployeesSalary();
    $total['employeesSalary'][] = $employeesSalary;
    $coffeeConsumption = $department->getConsumptionOfCoffee();
    $total['coffeeConsumption'][] = $coffeeConsumption;
    $paperConsumption = $department->getPaperConsumption();
    $total['paperConsumption'][] = $paperConsumption;
    $costPerPage = $department->getCostPerPage();
    $total['costPerPage'][] = $costPerPage;
    echo padRight($department->name, $columnWidth) .
        padLeft($employeesCount, $columnWidth) .
        padLeft($employeesSalary, $columnWidth) .
        padLeft($coffeeConsumption, $columnWidth) .
        padLeft($paperConsumption, $columnWidth) .
        padLeft($costPerPage, $columnWidth) . "\n";
}

echo padRight('Среднее', $columnWidth);
foreach ($total as $value) {
    echo padLeft(array_sum($value) / count($departments), $columnWidth);
}
echo "\n";
echo padRight('Всего', $columnWidth);
foreach ($total as $value) {
    echo padLeft(array_sum($value), $columnWidth);
}