<?php
class Company
{
	private $departaments = array();

	public function addDepartament($departament)
	{
		$this->departaments [] = $departament;
	}
	
	public function getDepartaments()
	{
		return $this->departaments;
	}
	
	public function getCountWorkers()
	{
		$count_workers = 0;
		foreach ($this->departaments as $departament) {
			$count_workers += $departament->getSumWorkers();
		}
		return $count_workers;
	}
	
	public function getAverageWorkers()
	{
		return $this->getCountWorkers()/count($this->departaments);
	}
	
	public function getCountSalary()
	{
		$count_salary = 0;
		foreach ($this->departaments as $departament) {
			$count_salary += $departament->getSumSalary();
		}
		return $count_salary;
	}
	
	public function getAverageSalary()
	{
		return $this->getCountSalary()/count($this->departaments);
	}
	
	public function getCountCoffee()
	{
		$count_coffee = 0;
		foreach ($this->departaments as $departament) {
			$count_coffee += $departament->getSumCoffee();
		}
		return $count_coffee;
	}
	
	public function getAverageCoffee()
	{
		return $this->getCountCoffee()/count($this->departaments);
	}
	
	public function getCountPages()
	{
		$count_pages = 0;
		foreach ($this->departaments as $departament) {
			$count_pages += $departament->getSumPages();
		}
		return $count_pages;
	}
	
	public function getAveragePages()
	{
		return $this->getCountPages()/count($this->departaments);
	}
	
		public function getCountSalaryForPage()
	{
		$count_salary_for_page = 0;
		foreach ($this->departaments as $departament) {
			$count_salary_for_page += $departament->getSalaryForPage();
		}
		return $count_salary_for_page;
	}
	
	public function getAverageSalaryForPage()
	{
		return $this->getCountSalaryForPage()/count($this->departaments);
	}
	
}


class Departament
{
	private $departament_name;
	private $workers = array();
	
	public function __construct($name)
	{
		$this->setDepartamentName($name);
	}
	
	public function getDepartamentName()
	{
		return $this->departament_name;
	}
	
	public function getWorkers()
	{
		return $this->workers;
	}
	public function setDepartamentName($name)
	{
		$this->departament_name = $name;
	}
	
	public function addWorker($worker)
	{
		$this->workers[] = $worker;
	}
	
	public function addWorkers($workers)
	{
		foreach ($workers as $worker) {
			$this->workers[] = $worker;
		}
	}
	public function getSumWorkers()
	{
		return count($this->workers);
		echo count($this->workers->salary);
	}
	
	public function getSumSalary()
	{
		$sum_salary = 0;
		foreach ($this->workers as $worker) {
			$sum_salary = $sum_salary+$worker->getSalary($worker);
		}
		return $sum_salary;
	}
	
	public function getSumCoffee()
	{
		$sum_coffee = 0;
		foreach ($this->workers as $worker) {
			$sum_coffee += $worker->getCoffee($worker);
		}
		return $sum_coffee;
	}
	
	public function getSumPages()
	{
		$sum_pages = 0;
		foreach ($this->workers as $worker) {
			$sum_pages += $worker->getPages($worker);
		}
		return $sum_pages;
	}
	
	public function getSalaryForPage()
	{
		 $salary = $this->getSumSalary();
		 $pages  = $this->getSumPages();
		 return round($salary/$pages, 3);
	}
	
	public function deleteWorker($number)
	{
		unset($this->workers[$number]);
	}
	
	public function getHeadWorker()
	{
		foreach ($this->workers as $worker) {
			if ($worker->getIsHead() == true) {
				return $worker;
			}
		}
	}
}


abstract class Worker 
{
	private $rank;
	private $proffesion;
	private $is_Head;
	private $salary;
	private $consumed_coffee;
	private $made_pages;
	
	public function __construct($rank, $proffesion, $is_Head, $salary, $consumed_coffe, $made_pages)
	{
		$this->setRank($rank);
		$this->setProffesion($proffesion);
		$this->setIsHead($is_Head);
		$this->setSalary($salary);
		$this->setConsumedCoffee($consumed_coffe);
		$this->setMadePages($made_pages);
	}
	
	public function setRank($rank)
	{
		$this->rank = $rank;
	}
	
	public function setProffesion($proffesion)
	{
		$this->proffesion = $proffesion;	
	}
	
	public function setIsHead($is_Head)
	{
		$this->is_Head = $is_Head;
	}
	
	public function setSalary($salary)
	{
		$this->salary = $salary;
	}
	
	public function setConsumedCoffee($consumed_coffee)
	{
		$this->consumed_coffee = $consumed_coffee;
	}
	
	public function setMadePages($made_pages)
	{
		$this->made_pages = $made_pages;
	}

	public function getSalary($worker)
	{
		$rank = $this->rank;
		if ($rank == 1) {
			$coef_salary = 1;
		}elseif ($rank == 2) {
			$coef_salary = 1.25;
		}elseif ($rank == 3) {
			$coef_salary = 1.5;
		}
		if ($this->is_Head == true) {
			$coef_head = 1.5;
		}else{
			$coef_head = 1;
		}
		return $this->salary*$coef_salary*$coef_head;
	}
	
	public function getCoffee($worker)
	{
		if ($this->is_Head == true) {
			$coef_head = 2;
		}else{
			$coef_head = 1;
		}
		return $this->consumed_coffee*$coef_head;
	}
	
	public function getPages($worker)
	{
		if ($this->is_Head == true) {
			$coef_head = 0;
		}else{
			$coef_head = 1;
		}
		return $this->made_pages*$coef_head;
	}
	
	public function getProffesion()
	{
	 	return $this->proffesion;
	}
	
	public function getRank()
	{
	 	return $this->rank;
	}
	
	public function getIsHead()
	{
	 	return $this->is_Head;
	}
}

class Manager extends Worker 
{
	public function __construct($rank, $is_Head)
	{
		parent::__construct($rank, 'Manager', $is_Head, 500, 20, 200);
	}
}

class Marketer extends Worker 
{
	public function __construct($rank, $is_Head)
	{
		parent::__construct($rank, 'Marketer', $is_Head, 400, 15, 150);
	}
}
class Engineer extends Worker 
{
	public function __construct($rank, $is_Head)
	{
		parent::__construct($rank, 'Engineer', $is_Head, 200, 5, 50);
	}
	
}
class Analyst extends Worker 
{
	static private $salary = 800;
	static private $coffee = 50;
	
	public function __construct($rank, $is_Head)
	{
		
		parent::__construct($rank, 'Analyst', $is_Head, Analyst::getSalaryForAnalyst(), Analyst::getCoffeeForAnalyst(), 5);
	}
	
	 static public function getSalaryForAnalyst()
	{
		return Analyst::$salary;
	}
	
	static public function setSalaryForAnalyst($new_salary)
	{
		Analyst::$salary = $new_salary;
	}
	
	static public function getCoffeeForAnalyst()
	{
		return Analyst::$coffee;
	}
	
	static public function setCoffeeForAnalyst($new_coffee)
	{
		Analyst::$coffee = $new_coffee;
	}
}

class Crisis 
{
	//Cократить в каждом департаменте 40% (округляя в большую сторону) инженеров, 
	//преимущественно самого низкого ранга. Если инженер является боссом, вместо него 
	//надо уволить другого инженера, не босса.
	public static function destroyWorkers($count_in_percent, $proffesion, $company)
	{
		foreach ($company->getDepartaments() as $departament) {
			$count_workers = 0;// Количество работников нужной профессии
			foreach ($departament->getWorkers() as $worker) {
				if ($worker->getProffesion() == $proffesion) {
					$count_workers ++;
				}
			}
			$sum_to_destroy = 0; // Количество работников которых нужно уволить исходя от заданых процентов
			$sum_to_destroy = ceil($count_workers*$count_in_percent-$count_workers);
			$rank = 1;
			for ($i = 0; $i < $sum_to_destroy; $rank++ ) {
				foreach ($departament->getWorkers() as $number => $worker) {
					if ($worker->getProffesion() == $proffesion &&
						$worker->getRank()       == $rank &&
						$i                       < $sum_to_destroy &&
						$worker->getIsHead()     == false ) {
							$departament->deleteWorker($number);
							$i++;
					}
				}
			}
		}
	}
	
	/** Увеличить базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров.
	 *  тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента
	 * (а бывшего руководителя вернуть к обычной работе)
	 * 
	 * Так же изменена зарпалата и кофе для аналитики при создание, то есть теперь если создать аналитика,
	 * то его запрплата будет такая же как и у измененых  "Analyst::setSalaryForAnalyst($salary);".
	 **/
	public static function increaseSalaryAndCoffee($salary, $coffee, $proffesion, $company)
	{
		Analyst::setSalaryForAnalyst($salary);
		Analyst::setCoffeeForAnalyst($coffee);
		foreach ($company->getDepartaments() as $departament) {
			foreach ($departament->getWorkers() as $worker) {
				if ($worker->getProffesion() == $proffesion) {
					$worker->setSalary($salary);
				}
				
				if ($worker->getProffesion() == $proffesion && $departament->getHeadWorker()->getProffesion() != $proffesion) {
				
					for ($rank = 3; $departament->getHeadWorker()->getProffesion() != $proffesion; $rank--) {
						foreach ($departament->getWorkers() as $worker) {
							if ($worker->getProffesion() == $proffesion && $worker->getRank() == $rank) {
								$worker->setIsHead(true);
							}
						}
					}
				}
			}
		}
	}
	
	/** каждом департаменте повысить 50% (округляя в большую сторону) 
	 * менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
	 **/
	public static function increaseRank($count_in_percent, $proffesion, $company) 
	{
		foreach ($company->getDepartaments() as $departament) {
			$count_workers = 0;// Количество работников нужной профессии
			foreach ($departament->getWorkers() as $worker) {
				if ($worker->getProffesion() == $proffesion && $worker->getRank() < 3) {
					$count_workers ++;
				}
			}
			$sum_to_destroy = 0;
			// Количество работников которых нужно уволить исходя от заданых процентов
			$sum_to_destroy = ceil($count_workers*$count_in_percent-$count_workers);
		}
		$i = 0;
		foreach ($company->getDepartaments() as $departament) {
			foreach ($departament->getWorkers() as $worker) {
				if ($worker->getProffesion() == $proffesion && $worker->getRank() < 3 && $i < $sum_to_destroy) {
					$worker->setRank($worker->getRank()+1);
					$i++;
				}
					
			}
		}
	}
}
function createWorkers($count, $rank, $proffesion, $is_Head)
{
	$workers_array = array();
	for ($i = 0; $i < $count; $i++) {
		$worker = new $proffesion($rank, $is_Head);
		$workers_array[] = $worker; 	
	}
	return $workers_array;
}
function createCompany()
{
$company = new Company;

$departament_purchase = new Departament("Purchase");
$departament_purchase->addWorkers(createWorkers(9, 1, 'Manager', false));
$departament_purchase->addWorkers(createWorkers(3, 2, 'Manager', false));
$departament_purchase->addWorkers(createWorkers(2, 3, 'Manager', false));
$departament_purchase->addWorkers(createWorkers(2, 1, 'Marketer', false));
$departament_purchase->addWorker(new Manager(2, true));
$company->addDepartament($departament_purchase);
 
$departament_sales = new Departament("Sales");
$departament_sales->addWorkers(createWorkers(12, 1, 'Manager', false));
$departament_sales->addWorkers(createWorkers(6, 1, 'Marketer', false));
$departament_sales->addWorkers(createWorkers(3, 1, 'Analyst', false));
$departament_sales->addWorkers(createWorkers(2, 2, 'Analyst', false));
$departament_sales->addWorker(new Marketer (2, true));
$company->addDepartament($departament_sales);
 
$departament_advertising = new Departament("advertising");
$departament_advertising->addWorkers(createWorkers(15, 1, 'Marketer', false));
$departament_advertising->addWorkers(createWorkers(10, 2, 'Marketer', false));
$departament_advertising->addWorkers(createWorkers(8, 1, 'Manager', false));
$departament_advertising->addWorkers(createWorkers(2, 1, 'Engineer', false));
$departament_advertising->addWorker(new Marketer (3, true));
$company->addDepartament($departament_advertising);
 
$departament_logistics = new Departament("Logistics");
$departament_logistics->addWorkers(createWorkers(13, 1, 'Manager', false));
$departament_logistics->addWorkers(createWorkers(5, 2, 'Manager', false));
$departament_logistics->addWorkers(createWorkers(5, 1, 'Engineer', false));
$departament_logistics->addWorker(new Manager(1, true));
$company->addDepartament($departament_logistics);

return $company;

}
function padRight($string, $length)
{
	$long_string = strlen ($string);
	$x = $length-$long_string;
	$space = str_repeat(" ",$x);
	echo $string.$space;
}
 
function padLeft($string, $length)
{
	$long_string = strlen ($string);
	$x = $length-$long_string;
	$space = str_repeat(" ",$x);
	echo $space.$string;
}

function printer($company)
{
	$col1 = 12;
	$col2 = 12;
	$col3 = 16;
 
	// Заголовок таблицы
	echo 	padRight ("Departaments",$col1).
   			padLeft("Workers", $col2) . 
	  		padLeft("Salary", $col2) . 
     		padLeft("Coffee", $col2) . 
     		padLeft("Pages", $col2) . 
     		padLeft("Salary/Pages", $col3) ."\n";
     	
	echo "----------------------------------------------------------------------\n";
	$departaments = $company->getDepartaments();
	foreach ($departaments as $departament) {
		echo padRight($departament->getDepartamentName(), $col2);
		echo padLeft($departament->getSumWorkers(), $col2);
		echo padLeft($departament->getSumSalary(), $col2);
		echo padLeft($departament->getSumCoffee(), $col2);
		echo padLeft($departament->getSumPages(), $col2);
		echo padLeft($departament->getSalaryForPage(), $col3)."\n";
	}
	
	echo "----------------------------------------------------------------------\n";
	echo padRight('Average', $col2);
	echo padLeft($company->getAverageWorkers(), $col2);
	echo padLeft($company->getAverageSalary(), $col2);
	echo padLeft($company->getAverageCoffee(), $col2);
	echo padLeft($company->getAveragePages(), $col2);
	echo padLeft($company->getAverageSalaryForPage(), $col3)."\n";
	echo "----------------------------------------------------------------------\n";
	echo padRight('VSEGO', $col2);
	echo padLeft($company->getCountWorkers(), $col2);
	echo padLeft($company->getCountSalary(), $col2);
	echo padLeft($company->getCountCoffee(), $col2);
	echo padLeft($company->getCountPages(), $col2);
	echo padLeft($company->getCountSalaryForPage(), $col3)."\n\n";
}

$company = createCompany();


printer($company);

/**
echo "1 АНТИ КРИЗИС \n----------------------------------------------------\n";
Crisis::destroyWorkers(1.4, 'Engineer', $company);
printer($company);
**/


/**
echo "2 АНТИ КРИЗИС \n----------------------------------------------------\n";
Crisis::increaseSalaryAndCoffee(1100, 75, 'Analyst', $company);
printer($company);
**/

/**
 * echo "3 АНТИ КРИЗИС \n----------------------------------------------------\n";
Crisis::increaseRank(1.5, 'Manager', $company);
printer($company);



