<?php

error_reporting(-1);
//mb_internal_encoding("utf-8");
 
//include("class.php");
/////////////////////////////////////////////// 
class Company{
	private $name; //название компании
	public $departments=array(); //департаменты  класса Department
	
	public function __construct($name){
		$this->name = $name;
	}
	
	//Добавляет новый департамент
	public function newDepartment(Department $department){
		if(!in_array($department,$this->departments)){
			$this->departments[]=$department;
		}
		else{
			throw new Exception("Нельзя добавить дважды один департамент");
		}
		
	}
	
	//Всего сотрудников
	public function countEmployees(){
		$empls=0;
		foreach($this->departments as $k=>$v){
			$empls+=$v->countEmployees();
		}
		return $empls;
	}
	//Расходы на зарплату
	public function countSalary(){
		$salary=0;
		foreach($this->departments as $k=>$v){
			$salary+=$v->countSalary();
		}
		return $salary;
	}
	//Расходы на кофе
	public function countCoffee(){
		$coffee=0;
		foreach($this->departments as $k=>$v){
			$coffee+=$v->countCoffee();
		}
		return $coffee;
	}
	//Расходы на страницы
	public function countPages(){
		$pages=0;
		foreach($this->departments as $k=>$v){
			$pages+=$v->countPages();
		}
		return $pages;
	}	
	//Средний расход рублей на страницу
	public function PagesBySalary(){
		$pbs=0;
		foreach($this->departments as $k=>$v){
			$pbs+=round($this->countSalary()/$this->countPages());
		}
		return $pbs;
	}
}

class Department{
	public $name; //название департамента 
	public $employees=array(); //сотрудники класса Employee
	
	public function __construct($name){
		$this->name = $name;
	}
	
	//Добавляет нового сотрудника
	public function newEmployee(Employee $employee){
			$this->employees[]=$employee;
	}
	
	//Удаляет сотрудника
	public function delEmployee(int $i){
		if(array_key_exists($i,$this->employees))
			unset($this->employees[$i]);
		else
			throw new Exception("delEmployee: нет такого сотрудника");
	}
	
	//Считает кол-во сотрудников в департаменте
	public function countEmployees(){
		return count($this->employees);
	}
	
	//Расходы на зарплату
	public function countSalary(){
		$salary=0;
		foreach($this->employees as $k=>$v){
			$salary+=$v->getSalary();
		}
		return $salary;
	}
	//Расходы на кофе
	public function countCoffee(){
		$coffee=0;
		foreach($this->employees as $k=>$v){
			$coffee+=$v->getCoffee();
		}
		return $coffee;
	}	
	//Расходы на страницы
	public function countPages(){
		$pages=0;
		foreach($this->employees as $k=>$v){
			$pages+=$v->getPages();
		}
		return $pages;
	}
	//Средний расход рублей на страницу
	public function PagesBySalary(){
		return $pbs=round($this->countSalary()/$this->countPages());
	}
}

abstract class Employee{
	public $range;  //[1;3]
	public $isBoss; //bool
	public static $rate; //int
	public static $coffee; //int
	public static $pages; //int
	
    public function __construct($range,$isBoss)
    {
		if(($range>=1)&&($range<=3))
			$this->range = $range;
		else
			throw new Exception("Ранг: [1;3]");
		
		if (is_bool($isBoss))
			$this->isBoss = $isBoss;
		else
			throw new Exception("Босс: boolean");
    }	
	
	public function getSalary(){
		$salary=static::$rate;
		if ($this->range==2)
			$salary*=1.25;
		elseif ($this->range==3)
			$salary*=1.5;
			
		if (($this->isBoss)){
			$salary*=1.5;
		}
		return $salary;
	}
	
	public function getCoffee(){
		$coffee=static::$coffee;	
		if (($this->isBoss)){
			$coffee*=2;
		}
		return $coffee;
	}
	
	public function getPages(){
		$pages=static::$pages;	
		if (($this->isBoss)){
			$pages=0;
		}
		return $pages;
	}
}

class Manager extends Employee{
	public static $rate=500;
	public static $coffee=20;
	public static $pages=200;
}


class Marketer extends Employee{
	public static $rate=400;
	public static $coffee=15;
	public static $pages=150;
}
class Engineer extends Employee{
	public static $rate=200;
	public static $coffee=5;
	public static $pages=50;
}
class Analyst extends Employee{
	public static $rate=800;
	public static $coffee=50;
	public static $pages=5;
}

//////////////////Ф-ии//////////////////////
function showCompanyTable($company){
	
	foreach($company->departments as $depNum=>$depClass){
		$department[$depNum]=$depClass;
	}

$col1 = 11;
$col2 = 10;
// Заголовок таблицы
echo padRight("Департамент", $col1) .
     padLeft("сотр.", $col2) . 
     padLeft("руб.", $col2) . 
     padLeft("кофе", $col2) . 
     padLeft("стр", $col2) . 
	 padLeft("руб/стр", $col2) . "\n";
echo "-----------------------------------------------------------------\n";
foreach ($department as $d){
	echo padRight($d->name,$col1).
     padLeft($d->countEmployees(), $col2) . 
     padLeft($d->countSalary(), $col2) . 
     padLeft($d->countCoffee(), $col2) . 
     padLeft($d->countPages(), $col2) . 
	 padLeft($d->PagesBySalary(), $col2) . "\n";
	
}
echo "-----------------------------------------------------------------\n";
$depNum=count($department);
echo padRight("Среднее",$col1).
    padLeft(round($company->countEmployees()/$depNum), $col2) . 
    padLeft(round($company->countSalary()/$depNum), $col2) . 
    padLeft(round($company->countCoffee()/$depNum), $col2) . 
    padLeft(round($company->countPages()/$depNum), $col2) . 
	padLeft(round($company->PagesBySalary()/$depNum), $col2) . "\n";

echo padRight("Всего",$col1).
    padLeft($company->countEmployees(), $col2) . 
    padLeft($company->countSalary(), $col2) . 
    padLeft($company->countCoffee(), $col2) . 
    padLeft($company->countPages(), $col2) . 
padLeft($company->PagesBySalary(), $col2) . "\n";


}
//Красивый вывод

function padRight($string,$charNumber){
	return $string.=str_repeat(' ',$charNumber-mb_strlen($string));
}

function padLeft($string,$charNumber){
	return $string=str_repeat(' ',$charNumber-mb_strlen($string)).$string; 
}
///////////////////////////////////////////
//Заполнение базы
$vector= new Company("Вектор");
$department[0]=new Department("Закупок");
$department[1]=new Department("Продаж");
$department[2]=new Department("Рекламы");
$department[3]=new Department("Логистики");

foreach ($department as $dep){
	$vector->newDepartment($dep);
}
//Закупок
for($i=0;$i<9;$i++){
	$employee[0][]=new Manager(1,false);
}
for($i=0;$i<3;$i++){
	$employee[0][]=new Manager(2,false);
}
for($i=0;$i<2;$i++){
	$employee[0][]=new Manager(3,false);
}
for($i=0;$i<2;$i++){
	$employee[0][]=new Marketer(1,false);
}
$employee[0][]=new Manager(2,true);
//Продаж
for($i=0;$i<12;$i++){
	$employee[1][]=new Manager(1,false);
}
for($i=0;$i<6;$i++){
	$employee[1][]=new Marketer(1,false);
}
for($i=0;$i<3;$i++){
	$employee[1][]=new Analyst(1,false);
}
for($i=0;$i<2;$i++){
	$employee[1][]=new Analyst(2,false);
}
$employee[1][]=new Marketer(2,true);
//Рекламы
for($i=0;$i<15;$i++){
	$employee[2][]=new Marketer(1,false);
}
for($i=0;$i<10;$i++){
	$employee[2][]=new Marketer(2,false);
}
for($i=0;$i<8;$i++){
	$employee[2][]=new Manager(1,false);
}
$employee[2][]=new Engineer(2,false);
$employee[2][]=new Engineer(1,false);
/*for($i=0;$i<2;$i++){
	$employee[2][]=new Engineer(1,false);
}*/
$employee[2][]=new Marketer(3,true);
//Логистики
for($i=0;$i<13;$i++){
	$employee[3][]=new Manager(1,false);
}
for($i=0;$i<5;$i++){
	$employee[3][]=new Manager(2,false);
}
$employee[3][]=new Engineer(1,true); /////
$employee[3][]=new Engineer(3,false);
$employee[3][]=new Engineer(1,false);
$employee[3][]=new Engineer(2,false);
/*for($i=0;$i<5;$i++){
	$employee[3][]=new Engineer(1,false);
}*/
$employee[3][]=new Manager(1,true);
//Записываем сотрудников в департаменты
foreach($employee as $k=>$v){
	foreach ($employee[$k] as $empl){
	$department[$k]->newEmployee($empl);
	}
}
/////////////////////////////////////////
//Вывод информации
showCompanyTable($vector);



							/*ООО Вектор и антикризисные меры*/
/////////////////////////////////////////////////////////	
//Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
$vector_orig=clone $vector; //делаем клон $vector_orig, редактируем $vector, выводим результат, потом опять возращаем $vector изначальные данные из $vector_orig и редактируем дальше


$engineers=[]; //массив всех инженеров в компании
foreach ($department as $depNum=>$depClass){
	foreach($depClass->employees as $empNum=>$empClass){
		if(get_class($empClass)=="Engineer"){
			$engArr["id"]=$empNum;
			$engArr["range"]=$empClass->range;
			$engineers[$depNum][]=$engArr;
		}
	}
}

// Сортировка инженеров по рангу
foreach($engineers as $depNum=>$depEmpls){
	foreach ($engineers[$depNum] as $key => $row) {
		$range[$key] = $row['range'];
	}
	array_multisort($range, SORT_ASC,$engineers[$depNum]);
}


//удаление
foreach($engineers as $depNum=>$depEmpls){
	$d=ceil(count($depEmpls) * 0.4); //сколько нужно удалить в департаменте
	$i=0; //сколько уже удалено
	foreach($depEmpls as $empNum=>$empId){
		if($i<$d){
			$empId=$empId['id']; //костыль
			if(($department[$depNum]->employees[$empId]->isBoss)==false){ //если не босс
				$department[$depNum]->delEmployee($empId);
				$i++;
			}
		}
		else{
			break;
		}
	}
}
echo "\n\n\n		После антикризисных мер 1\n\n";
showCompanyTable($vector);
$vector=clone $vector_orig; //возвратили исходные данные
/////////////////////////////////////////////////////////
//Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров. 
Analyst::$rate = 1100;
Analyst::$coffee = 75;
//В тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)

//Ищем в департаментах босса-не-аналитика и аналитиков-не-боссов
$analysts=[];
foreach ($department as $depNum=>$depClass){ //в каждом департаменте
	foreach($depClass->employees as $empNum=>$empClass){ //каждый сотрудник департамента
		if($empClass->isBoss){ //если босс
			if(get_class($empClass)!="Analyst"){ //и не аналитик
				$boss[$depNum]=$empNum; //пишем id босса
			}
		}
		else{ //если не босс
			if(get_class($empClass)=="Analyst"){ //но аналитик
				//записываем в массив аналитиков
				$engArr["id"]=$empNum;
				$engArr["range"]=$empClass->range;
				$analysts[$depNum][]=$engArr;			
			}
		}
	}
}
//если босс не аналитик и есть в отделе аналитики
foreach ($analysts as $depNum=>$empl){
	if (isset($boss[$depNum])){ //Если перем есть, то это точно не аналитик
		////сортируем аналитиков по рангу
		foreach ($empl as $key => $row) {
			$range[$key] = $row['range'];
		}
		array_multisort($range, SORT_ASC,$empl);
		////
		$last=count($empl)-1; //последний - самый старший
		$doHimBoss=$empl[$last]['id']; //получим его id
		
		$department[$depNum]->employees[$doHimBoss]->isBoss=true; //сделали боссом старшего аналитика
		$department[$depNum]->employees[$boss[$depNum]]->isBoss=false; //текущий босс - не босс
	}
}
echo "\n\n\n		После антикризисных мер 2\n\n";
showCompanyTable($vector);
$vector=clone $vector_orig; //возвратили исходные данные
/////////////////////////////////////////////////////////////////
//В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
foreach ($department as $depNum=>$depClass){ //в каждом департаменте
	
	$managerNum=0;
	foreach($depClass->employees as $empNum=>$empClass){ //каждый сотрудник департамента
		if((get_class($empClass)=="Manager") && ($empClass->range<3)){
				$managerNum++;
		}
	}

	for($i=0;$i<$managerNum;$i++){
			if(get_class($depClass->employees[$i])=="Manager"){
				if($depClass->employees[$i]->range<3){
					$depClass->employees[$i]->range++;
				}
			}		
	}
}

//
echo "\n\n\n		После антикризисных мер 3\n\n";
showCompanyTable($vector);


//print_r($vector);