<?php

error_reporting(-1);
mb_internal_encoding("UTF-8");

class Department
{	
	public $name;
	public $staff = array();
	public $chief;
	
	public function __construct($name)
	{
		$this->name = $name;
	}
	
	public function setChief($chief)
	{
		$this->chief = $chief;
	}
	
	public function addEmployee(array $employees)
	{
		foreach ($employees as $workers) {
			$this->staff[] = $workers;
		}
	}
	
	public function getTotalSalary()
	{	
		$totalSalary = 0;
		foreach ($this->staff as $type) {
			$totalSalary += $type->getSalary(false);
		}
		
		$totalSalary += $this->chief->getSalary(true);
		
		return $totalSalary;
	}
	
	public function getTotalCoffee()
	{
		$totalCoffee = 0;
		foreach ($this->staff as $type) {
			$totalCoffee += $type->coffee;
		}
		
		$totalCoffee += $this->chief->getChiefCoffee();
		
		return $totalCoffee;
	}
	
	public function getTotalOutput()
	{
		$totalOutput = 0;
		foreach ($this->staff as $type) {
			$totalOutput += $type->output;
		}
		return $totalOutput;
	}
}

abstract class Employee
{	
	const RANK_1 = 1;
	const RANK_2 = 2;
	const RANK_3 = 3;
	
	const MANAGER = "me";
	const MARKETER = "ma";
	const ENGINEER = "en";
	const ANALYST = "an";
	
	public $baseSalary, $coffee, $output, $rank;
	
	public function __construct($rank)
	{
		$this->rank = $rank;
	}
	
	public function getSalary($isChief)
	{
		$salaryMult = array(
			self::RANK_1 => 1,
			self::RANK_2 => 1.25,
			self::RANK_3 => 1.5,
		);
		
		if ($isChief == false) {
			return $this->baseSalary * $salaryMult[$this->rank];
		} else {
			return $this->baseSalary * $salaryMult[$this->rank] * 1.5;
		}
	}
	
	public function getChiefCoffee()
	{
		return $this->coffee*2;
	}
}

class Manager extends Employee
{	
	public $baseSalary = 500;
	public $coffee = 20;
	public $output = 200;
}

class Marketer extends Employee
{
	public $baseSalary = 400;
	public $coffee = 15;
	public $output = 150;
}

class Engineer extends Employee
{
	public $baseSalary = 400;
	public $coffee = 5;
	public $output = 50;
}

class Analyst extends Employee
{
	public $salary = 400;
	public $coffee = 50;
	public $output = 5;
}

class EmployeeFactory
{
	public static function chooseEmployee($name, $rank)
	{
		if ($name == "me") {
			return new Manager($rank);
		} elseif ($name == "ma") {
			return new Marketer($rank);
		} elseif ($name == "en") {
			return new Engineer($rank);
		} elseif ($name == "an") {
			return new Analyst($rank);
		}
	}
	
	public static function createEmployees($employees)
	{
		$new = array();
		foreach ($employees as $workers) {
			
			preg_match_all('/^(\d*)(\w{2})([1-3])$/i', $workers, $res, PREG_SET_ORDER);
			$number = $res[0][1];
			$name = $res[0][2];
			$rank = $res[0][3];
			
			if (!$number) {
				$number = 1;
			}
			
			for ($i = 0; $i < $number; $i++) {
			
				$new[] = self::chooseEmployee($name, $rank);
			}
		}
		return $new;
	}
	
	public static function createChief($employee)
	{
		preg_match_all('/^(\w{2})([1-3])$/i', $employee, $res, PREG_SET_ORDER);
		$name = $res[0][1];
		$rank = $res[0][2];
		
		$chief = self::chooseEmployee($name, $rank);
		$chief->output = 0;
		
		return $chief;
	}
}

$purchase = new Department("Закупки");
$purchase->addEmployee(EmployeeFactory::createEmployees(array("9me1", "3me2", "2me3", "2ma1")));
$purchase->setChief(EmployeeFactory::createChief("me2"));

$sales = new Department("Продажи");
$sales->addEmployee(EmployeeFactory::createEmployees(array("12me1", "6ma1", "3an1", "2an2")));
$sales->setChief(EmployeeFactory::createChief("ma2"));

$ads = new Department("Реклама");
$ads->addEmployee(EmployeeFactory::createEmployees(array("15ma1", "10ma2", "8me1", "2en1")));
$ads->setChief(EmployeeFactory::createChief("ma3"));

$log = new Department("Логистика");
$log->addEmployee(EmployeeFactory::createEmployees(array("13me1", "5me2", "5en1")));
$log->setChief(EmployeeFactory::createChief("me1"));

$departments = array($purchase, $sales, $ads, $log);

// ВЫВОД
function padLeft($string, $length) 
{
	$countString = mb_strlen($string);
	if ($countString < $length) {
		$pad = $length - $countString;
		$string = str_repeat(" ", $pad).$string;
	}
	return $string;
}

function padRight($string, $length) 
{
	$countString = mb_strlen($string);
	if ($countString < $length) {
		$pad = $length - $countString;
		$string .= str_repeat(" ", $pad);
	}
	return $string;
}

// Ширина колонок
$col1 = 15;
$col2 = 12;
$col3 = 12;
$col4 = 12;
$col5 = 12;
$col6 = 20;

// Заголовок таблицы
echo padRight("Департамент", $col1) .
     padLeft("сотр.", $col2) .
     padLeft("тугр.", $col3) .
     padLeft("кофе", $col4) . 
     padLeft("стр.", $col5) . 
     padLeft("тугр./стр.", $col6) ."\n";

// Граница заголовков
echo str_repeat("-", 70)."\n";

$sumCount = 0;
$sumSalary = 0;
$sumCoffee = 0;
$sumOutput = 0;
$sumExpence = 0;

foreach ($departments as $department) {

	echo padRight($department->name, $col1) .
	     padLeft(count($department->staff) + 1, $col2) .
	     padLeft($department->getTotalSalary(), $col3) .
	     padLeft($department->getTotalCoffee(), $col4) . 
	     padLeft($department->getTotalOutput(), $col5) . 
	     padLeft(round($department->getTotalSalary()/$department->getTotalOutput(), 2), $col6) ."\n";
	     $sumCount += count($department->staff) + 1;
	     $sumSalary += $department->getTotalSalary();
	     $sumCoffee += $department->getTotalCoffee();
	     $sumOutput += $department->getTotalOutput();
	     $sumExpence += round($department->getTotalSalary()/$department->getTotalOutput(), 2);
}

$n = count($departments);

echo padRight("Среднее", $col1) .
	     padLeft($sumCount / $n, $col2) .
	     padLeft($sumSalary / $n, $col3) .
	     padLeft($sumCoffee / $n, $col4) . 
	     padLeft($sumOutput / $n, $col5) . 
	     padLeft($sumExpence / $n, $col6) ."\n";
	     
echo padRight("Всего", $col1) .
	     padLeft($sumCount, $col2) .
	     padLeft($sumSalary, $col3) .
	     padLeft($sumCoffee, $col4) . 
	     padLeft($sumOutput, $col5) . 
	     padLeft($sumExpence, $col6) ."\n";