<?php
header('Content-type: text/plain');

abstract class  Employee
{
    private $rank;
    private $boss;
    protected $data;
    public const TYPE_EMPLOYEES = ['manager' => '0',
        'marketer' => '1',
        'engineer' => '2',
        'analytic' => '3'];

    function __construct(int $rank, int $boss) {
        $this->rank = $rank;
        $this->boss = $boss;
    }

    public function getMoney() {
        $money = $this->data['money'];
        if ($this->rank == 2 ) {
            $money *= 1.25;
        } elseif ($this->rank == 3) {
            $money *= 1.5;
        }
        if ($this->boss) {
            $money *= 1.5;
        }
        return $money;
    }

    public function getCoffee() {
        $coffee = $this->data['coffee'];
        if ($this->boss) {
            $coffee *= 2;
        }
        return $coffee;
    }

    public function getPages() {
        $pages = $this->data['pages'];
        if ($this->boss) {
            $pages = 0;
        }
        return $pages;
    }
}

class Manager extends Employee
{
    protected $data = ['money' => '500',
        'coffee' => '20',
        'pages' => '200'];
}

class Marketer extends Employee
{
    protected $data = ['money' => '400',
        'coffee' => '15',
        'pages' => '150'];
}

class Engineer extends Employee
{
    protected $data = ['money' => '200',
        'coffee' => '5',
        'pages' => '50'];
}

class Analytic extends Employee
{
    protected $data = ['money' => '800',
        'coffee' => '50',
        'pages' => '5'];
}

class Department
{
    private $name;
    private $employees = [];

    function __construct(string $department) {
        $this->name = $department;
    }
    /* Добавляем работников в департамент */
    public function createEmployee(int $prof, int $rank, int $boss, int $count) {
        for ($i = 0; $i < $count; $i++) {
            switch ($prof) {
                case Employee::TYPE_EMPLOYEES['manager']:
                    $this->employees[] = new Manager($rank, $boss);
                    break;
                case Employee::TYPE_EMPLOYEES['marketer']:
                    $this->employees[] = new Marketer($rank, $boss);
                    break;
                case Employee::TYPE_EMPLOYEES['engineer']:
                    $this->employees[] = new Engineer($rank, $boss);
                    break;
                case Employee::TYPE_EMPLOYEES['analytic']:
                    $this->employees[] = new Analytic($rank, $boss);
                    break;
            }

        }
    }

    /* Создаём массив со статистикой департамента */
    public function getDepStat() {
        $depData = ['name' => $this->name,
            'count' => count($this->employees),
            'money' => 0,
            'coffee' => 0,
            'pages' => 0,
            'average' => 0];

        foreach ($this->employees as $item) {
            $depData['money'] += $item->getMoney();
            $depData['coffee'] += $item->getCoffee();
            $depData['pages'] += $item->getPages();
        }
        $depData['average'] = round($depData['money'] / $depData['pages'], 1);

        return $depData;
    }
}

class Company
{
    private $name;
    private $departments;

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

    public function addDepartment($department) {
        $this->departments[] = $department;
    }

    /* Получаем статистику департаментов и заносим в массив */
    public function getCompanyStat() {
        foreach ($this->departments as $item) {
            $companyStat[] = $item->getDepStat();
        }
        return $companyStat;
    }

    /* Полная статистика компании */
    public function totalCompanyStat() {
        $statistic = $this->getCompanyStat();
        $totalStat = ['name' => 'Всего',
            'count' => 0,
            'money' => 0,
            'coffee' => 0,
            'pages' => 0];

        foreach ($statistic as $item) {
            $totalStat['count'] += $item['count'];
            $totalStat['money'] += $item['money'];
            $totalStat['coffee'] += $item['coffee'];
            $totalStat['pages'] += $item['pages'];
        }
        return $totalStat;
    }
    /* Средние значения полной статистики */
    public function averageCompanyStat() {
        $depCount = count($this->departments);
        $statistic = $this->totalCompanyStat();

        $averageStat = ['name' => 'Среднее',
            'money' => 0,
            'coffee' => 0,
            'pages' => 0,
            'average' => 0];

        $averageStat['count'] = round($statistic['count'] / $depCount, 1);
        $averageStat['money'] = round($statistic['money'] / $depCount, 1);
        $averageStat['coffee'] = round($statistic['coffee'] / $depCount, 1);
        $averageStat['pages'] = round($statistic['pages'] / $depCount, 1);
        $averageStat['average'] = round($statistic['money'] / $statistic['pages'], 1);
        return $averageStat;
    }

}

/* Создаём компанию и добавляем в неё департаменты */
$company = new Company("Вектор");

$dep = new Department("Закупок");
$dep1 = new Department("Продаж");
$dep2 = new Department("Рекламы");
$dep3 = new Department("Логистики");

$company->addDepartment($dep);
$company->addDepartment($dep1);
$company->addDepartment($dep2);
$company->addDepartment($dep3);

$dep->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "1", "0", "9");
$dep->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "2", "0", "3");
$dep->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "3", "0", "2");
$dep->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "1", "0", "2");
$dep->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "2", "1", "1");

$dep1->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "1", "0", "12");
$dep1->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "1", "0", "6");
$dep1->createEmployee(Employee::TYPE_EMPLOYEES['analytic'], "1", "0", "3");
$dep1->createEmployee(Employee::TYPE_EMPLOYEES['analytic'], "2", "0", "2");
$dep1->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "2", "1", "1");

$dep2->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "1", "0", "15");
$dep2->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "2", "0", "10");
$dep2->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "1", "0", "8");
$dep2->createEmployee(Employee::TYPE_EMPLOYEES['engineer'], "1", "0", "2");
$dep2->createEmployee(Employee::TYPE_EMPLOYEES['marketer'], "3", "1", "1");

$dep3->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "1", "0", "13");
$dep3->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "2", "0", "5");
$dep3->createEmployee(Employee::TYPE_EMPLOYEES['engineer'], "1", "0", "5");
$dep3->createEmployee(Employee::TYPE_EMPLOYEES['manager'], "1", "1", "1");


$companyStat = $company->getCompanyStat();
$totalStat = $company->totalCompanyStat();
$averageStat = $company->averageCompanyStat();

/* Вывод информации */
$col1 = 15;
$col2 = 10;

/* Заголовок */
echo padLeft("Департамент", $col1) .
    padLeft("сотр.", $col2) .
    padLeft("тугр.", $col2) .
    padLeft("кофе", $col2) .
    padLeft("стр.", $col2) .
    padLeft("тугр./стр.", $col2) . "\n\n";

/* Перебор департаментов */
foreach ($companyStat as $item) {
    echo padLeft($item['name'],$col1) .
        padLeft($item['count'], $col2) .
        padLeft($item['money'], $col2) .
        padLeft($item['coffee'], $col2) .
        padLeft($item['pages'], $col2) .
        padLeft($item['average'], $col2) . "\n";
}
/* Всего */
echo padLeft($totalStat['name'],$col1) .
    padLeft($totalStat['count'], $col2) .
    padLeft($totalStat['money'], $col2) .
    padLeft($totalStat['coffee'], $col2) .
    padLeft($totalStat['pages'], $col2) . "\n";

/* Среднее */
echo padLeft($averageStat['name'],$col1) .
    padLeft($averageStat['count'], $col2) .
    padLeft($averageStat['money'], $col2) .
    padLeft($averageStat['coffee'], $col2) .
    padLeft($averageStat['pages'], $col2) .
    padLeft($averageStat['average'], $col2);

function padLeft($value, $col){
    $count = iconv_strlen($value); // mb_strlen не работает
    if ($col > $count) {
        $value = $value . str_repeat(" ", $col - $count);
    }
    return $value;
}
