<?php
 
error_reporting(-1);
mb_internal_encoding('utf-8');
 
$rates = array(
	'Me'=>500,
	'Ma'=>400,
	'En'=>200,
	'An'=>800
	);
$coffe = array(
	'Me'=>20,
	'Ma'=>15,
	'En'=>5,
	'An'=>50
	);
$documentation = array(
	'Me'=>200,
	'Ma'=>150,
	'En'=>50,
	'An'=>5
	);
 
class Employees
{
	public $department;
	public $boss;
	public $employee;
	public $rates;
 
	public function __construct($department, $position, $rank, $boss, $quantity, $rates)
	{
		if ($rank == 1){
			$factor = 1;
		}elseif($rank == 2){
			$factor = 1.25;
		}elseif($rank == 3){
			$factor = 1.5;
		}
		$this->department = $department;
		if ($boss == true){
			$this->boss['position'] = $position;
			$this->boss['rank'] = $rank;
			$this->boss['quantity'] = $quantity;
			$this->boss['factor'] = $factor;
		}else{
			$this->employee['position'] = $position;
			$this->employee['rank'] = $rank;
			$this->employee['quantity'] = $quantity;
			$this->employee['factor'] = $factor;
		}
		$this->rates = $rates;
	}
}
 
class EmployeeOrder
{
	public $department;
	public $boss;
	public $employees;
	public $rates;
	public $coffe;
 
	public function __construct($workers, $coffe)
	{
		foreach ($workers as $worker)
		{
		if ($worker->boss == true){
			$this->boss = $worker->boss;
			}else{
			$this->employees[] = $worker->employee;
			}
		$this->department = $worker->department;
		}
		$this->rates = $worker->rates;
		$this->coffe = $coffe;
	}
	
	function crysis()
	{
		if (!function_exists('multisort')) {
		function multisort($array, $index) 
	    { 
	    for($i = 0; $i < count($array); $i++) 
	    { 
	    $el_arr = $array[$i][$index];
	    $new_arr[] = $el_arr; 
	    } 
	    asort($new_arr); 
	    $keys = array_keys($new_arr); 
	    for($key=0; $key<count($keys); $key++) 
	    $result[] = $array[$keys[$key]]; 
	    return $result; 
	    } 
		}
	    
		if ($this->boss['position'] == 'En')
		{
			$sum = 1;
		}else{
			$sum = 0;
		}
		foreach($this->employees as $employees)
		{
			if($employees['position'] == 'En')
			{
			$sum = $employees['quantity']+$sum;
			}
		}$firedWorkers = ceil($sum*0.4);
		$q=0;
		foreach(multisort($this->employees, 'rank') as $employees)
		{
			if ($employees['position'] == 'En')
			{
				if ($firedWorkers != 0){
					if($employees['quantity'] > $firedWorkers)
					{
						$employees['quantity'] = $employees['quantity'] - $firedWorkers;
						$firedWorkers = 0;
					}else{
						$firedWorkers = $firedWorkers - $employees['quantity'];
						$employees['quantity'] = 0;
					}
				}
			}
			$employee[$q]=$employees;
			$q++;
 
		}return array('employees' => $employee, 'boss' => $this->boss, 
		'rates' => $this->rates, 'coffe' => $this->coffe);
	}
 
	function crysis2()
	{
		$this->rates['An'] = 1100;
		$this->coffe['An'] = 75;
 
		if (!function_exists('array_max')) {
		function array_max($arr)
		{
	  	static $max;
	  	foreach($arr as $array){
    		foreach($array as $key => $value)
			{
				if($key == 'rank'){
    				if( ! is_array($value))
    				{
    			     	$max = ($max >= $value) ? $max : $value;
    			  	}
        			else
        			{
        		 	array_max($value);    
        			}
    				}else{
    				continue;
    				}
			}
		}return $max;
		}
		}
		$analysts = array();
		foreach($this->employees as $employee)
		{
			if ($employee['position'] == 'An')
			{
				$analysts[] = $employee;
			}
		}
		if($this->boss['position'] != 'An' && $analysts != NULL)
		{
		$boss = array();
		$employees = array();
		$firedBoss = array();
		foreach($this->employees as $employee)
		{
			if($employee['position'] == 'An' && $employee['rank'] == array_max($analysts))
			{
				$boss = $employee;
				$boss['quantity'] = 1;
				$employee['quantity'] = $employee['quantity'] - 1;
				$firedBoss = $this->boss;
			}$employees[] = $employee;
		}$employees[] = $firedBoss;
		}else{
			$employees = $this->employees;
			$boss = $this->boss;
		}
		return array('employees' => $employees, 'boss' => $boss, 
		'rates' => $this->rates, 'coffe' => $this->coffe);
	}
	
	function crysis3()
	{
		$sum1 = 0;
		$sum2 = 0;
		foreach($this->employees as $employees)
		{
			if($employees['position'] == 'Me' && $employees['rank'] == 1)
			{
			$sum1 = $employees['quantity'] + $sum1;
			}
			if($employees['position'] == 'Me' && $employees['rank'] == 2)
			{
			$sum2 = $employees['quantity'] + $sum2;
			}
		}$promotedWorkersRank1 = ceil($sum1*0.5);
		$promotedWorkersRank2 = ceil($sum2*0.5);
		$correction = ceil(($sum1+$sum2)*0.5);
		
		if($correction < $promotedWorkersRank1+$promotedWorkersRank2)
		{
			$difference = ($promotedWorkersRank1 + $promotedWorkersRank2) - $correction;
			if($promotedWorkersRank1 > $promotedWorkersRank2)
			{
				$promotedWorkersRank1 = $promotedWorkersRank1 - $difference;
			}else{
				$promotedWorkersRank2 = $promotedWorkersRank2 - $difference;
			}
		}
		$boss = array();
		$workers = array();
		if ($this->boss['position'] == 'Me' && $this->boss['rank'] != 3)
		{
			$boss = $this->boss;
			$boss['rank'] = $boss['rank'] + 1;
			if($boss['rank'] == 2)
			{
				$boss['factor'] = 1.25;
			}else{
				$boss['factor'] = 1.5;
			}
		}else{
			$boss = $this->boss;
		}
		foreach($this->employees as $employees)
		{
			if($employees['position'] == 'Me' && $employees['rank'] != 3){
				if($employees['position'] == 'Me' && $employees['rank'] == 1)
				{
					if ($promotedWorkersRank1 != 0)
					{
						if($employees['quantity'] < $promotedWorkersRank1)
						{
							$workers = $employees;
							$workers['quantity'] = $employees['quantity'];
							$workers['rank'] = 2;
							$workers['factor'] = 1.25;
							$promotedWorkersRank1 = $promotedWorkersRank1 - $employees['quantity'];
							$employees['quantity'] = 0;
						}else{
							$workers = $employees;
							$workers['quantity'] = $promotedWorkersRank1;
							$workers['rank'] = 2;
							$workers['factor'] = 1.25;
							$employees['quantity'] = $employees['quantity'] - $promotedWorkersRank1;
							$promotedWorkersRank1 = 0;
						}
					}
				}
				elseif($employees['position'] == 'Me' && $employees['rank'] == 2)
				{
					$workers = $employees;
					if ($promotedWorkersRank2 != 0)
					{
						if($employees['quantity'] < $promotedWorkersRank2)
						{
							$workers = $employees;
							$workers['quantity'] = $employees['quantity'];
							$workers['rank'] = 3;
							$workers['factor'] = 1.5;
							$promotedWorkersRank2 = $promotedWorkersRank2 - $employees['quantity'];
							$employees['quantity'] = 0;
						}else{
							$workers = $employees;
							$workers['quantity'] = $promotedWorkersRank2;
							$workers['rank'] = 3;
							$workers['factor'] = 1.5;
							$employees['quantity'] = $employees['quantity'] - $promotedWorkersRank2;
							$promotedWorkersRank2 = 0;
						}
					}
				}
			}else{
				$employee[] = $employees;
				continue;
			}
			$employee[] = $employees;
			$employee[] = $workers;
			
		}return array('employees' => $employee, 'boss' => $boss, 
		'rates' => $this->rates, 'coffe' => $this->coffe);
	}
}

class Department 
{
	public $departmentName;
	public $personelAmount;
	public $departmentSalary;
	public $departmentCoffe;
	public $departmentDocumentation;
	public $salaryPerPages;
	
	public function __construct($workers, $documentation)
	{
		$this->departmentName = $workers->department;
		foreach ($workers->employees as $employees)
		{
			$this->departmentSalary = $workers->rates[$employees['position']] * $employees['factor']
			* $employees['quantity'] + $this->departmentSalary;
			$this->departmentCoffe = $workers->coffe[$employees['position']] * $employees['quantity'] + $this->departmentCoffe;
			$this->departmentDocumentation = ($documentation[$employees['position']]
			* $employees['quantity']) + $this->departmentDocumentation ;
			$this->personelAmount =  $employees['quantity'] + $this->personelAmount;
		}
		$this->departmentSalary = $workers->rates[$workers->boss['position']] * $workers->boss['factor'] * 1.5
		* $workers->boss['quantity'] + $this->departmentSalary;
		$this->departmentCoffe = $workers->coffe[$workers->boss['position']]* 2 * $workers->boss['quantity'] + $this->departmentCoffe;
		$this->personelAmount =  $workers->boss['quantity'] + $this->personelAmount;
		$this->salaryPerPages = round($this->departmentSalary / $this->departmentDocumentation, 2);
	}
}

class Company
{
	public $total = 'Всего';
	public $totalPersonelAmount;
	public $totalSalary;
	public $totalCoffe;
	public $totalDocumentation;
	public $totalSalaryPerPages;
	
	public $average = 'Среднее';
	public $averagePersonelAmount;
	public $averageSalary;
	public $averageCoffe;
	public $averageDocumentation;
	public $averageSalaryPerPages;
	
	public function __construct($departments)
	{
		foreach ($departments as $department)
		{
			$this->totalPersonelAmount = $department->personelAmount + $this->totalPersonelAmount;
	 		$this->totalSalary = $department->departmentSalary + $this->totalSalary;
	 		$this->totalCoffe = $department->departmentCoffe + $this->totalCoffe;
			$this->totalDocumentation = $department->departmentDocumentation + $this->totalDocumentation;
			$this->totalSalaryPerPages = $department->salaryPerPages + $this->totalSalaryPerPages;
		}
		$this->averagePersonelAmount = $this->totalPersonelAmount / count($departments);
		$this->averageSalary = round($this->totalSalary / count($departments), 2);
		$this->averageCoffe = round($this->totalCoffe / count($departments), 2);
		$this->averageDocumentation = round($this->totalDocumentation / count($departments), 2);
		$this->averageSalaryPerPages = round($this->totalSalaryPerPages / count($departments), 2);
	}
}

  function padRight($q, $w){
 return implode("", (array_merge(preg_split('//u', $q, 0, PREG_SPLIT_NO_EMPTY), array_fill(0, $w-mb_strlen($q), " "))));
 }
  function padLeft($q, $w){
 return implode("", (array_merge(array_fill(0, $w-mb_strlen($q), " "), preg_split('//u', $q, 0, PREG_SPLIT_NO_EMPTY))));
 }
  function crysisReplace($object, $replacement){
  	$object->employees = $replacement['employees'];
  	$object->boss = $replacement['boss'];
  	$object->rates = $replacement['rates'];
  	$object->coffe = $replacement['coffe'];
  	return $object;
  }
 
$workers1 = array(
new Employees ('Закупок', 'Me', 1, false, 9, $rates),
new Employees ('Закупок', 'Me', 2, false, 3, $rates),
new Employees ('Закупок', 'Me', 3, false, 2, $rates),
new Employees ('Закупок', 'Ma', 1, false, 2, $rates),
new Employees ('Закупок', 'Me', 2, true, 1, $rates)
);
$workers2 = array(
new Employees ('Продаж', 'Me', 1, false, 12, $rates),
new Employees ('Продаж', 'Ma', 1, false, 6, $rates),
new Employees ('Продаж', 'An', 1, false, 3, $rates),
new Employees ('Продаж', 'An', 2, false, 2, $rates),
new Employees ('Продаж', 'Ma', 2, true, 1, $rates)
);
$workers3 = array(
new Employees ('Рекламы', 'Ma', 1, false, 15, $rates),
new Employees ('Рекламы', 'Ma', 2, false, 10, $rates),
new Employees ('Рекламы', 'Me', 1, false, 8, $rates),
new Employees ('Рекламы', 'En', 1, false, 2, $rates),
new Employees ('Рекламы', 'Ma', 3, true, 1, $rates)
);
$workers4 = array(
new Employees ('Логистики', 'Me', 1, false, 13, $rates),
new Employees ('Логистики', 'Me', 2, false, 5, $rates),
new Employees ('Логистики', 'En', 1, false, 5, $rates),
new Employees ('Логистики', 'Me', 1, true, 1, $rates)
);
$departments = array(
new Department((new EmployeeOrder($workers1, $coffe)), $documentation),
new Department((new EmployeeOrder($workers2, $coffe)), $documentation),
new Department((new EmployeeOrder($workers3, $coffe)), $documentation),
new Department((new EmployeeOrder($workers4, $coffe)), $documentation)
);

function departmentStack1($obj, $documentation)
{
	return new Department(crysisReplace($obj, $obj->crysis()), $documentation);
}

function departmentStack2($obj, $documentation)
{
	return new Department(crysisReplace($obj, $obj->crysis2()), $documentation);
}

function departmentStack3($obj, $documentation)
{
	return new Department(crysisReplace($obj, $obj->crysis3()), $documentation);
}

$departmentsCrysis1 = array(
departmentStack1((new EmployeeOrder($workers1, $coffe)), $documentation),
departmentStack1((new EmployeeOrder($workers2, $coffe)), $documentation),
departmentStack1((new EmployeeOrder($workers3, $coffe)), $documentation),
departmentStack1((new EmployeeOrder($workers4, $coffe)), $documentation)
);

$departmentsCrysis2 = array(
departmentStack2((new EmployeeOrder($workers1, $coffe)), $documentation),
departmentStack2((new EmployeeOrder($workers2, $coffe)), $documentation),
departmentStack2((new EmployeeOrder($workers3, $coffe)), $documentation),
departmentStack2((new EmployeeOrder($workers4, $coffe)), $documentation)
);

$departmentsCrysis3 = array(
departmentStack3((new EmployeeOrder($workers1, $coffe)), $documentation),
departmentStack3((new EmployeeOrder($workers2, $coffe)), $documentation),
departmentStack3((new EmployeeOrder($workers3, $coffe)), $documentation),
departmentStack3((new EmployeeOrder($workers4, $coffe)), $documentation)
);
$company = new Company ($departments);
$crysisCompany1 = new Company($departmentsCrysis1);
$crysisCompany2 = new Company($departmentsCrysis2);
$crysisCompany3 = new Company($departmentsCrysis3);

function printData($departments, $company, $headline)
{
$col1 = 20;
$col2 = 8;
$col3 = 12;
$col4 = 12;
$col5 = 12;
$col6 = 12;
$col7 = 50;
if($headline == 0){
echo padRight("Департамент", $col1) .
     padLeft("сотр.", $col2) . 
     padLeft("тугр.", $col3) . 
     padLeft("кофе", $col4) .
     padLeft("стр.", $col5) .
     padLeft("тугр./стр.", $col6) . "\n" . 
     implode("", array_fill(0, 40, '--')) . "\n";
}else{
	echo padLeft ('Анти-кризисная мера #'."{$headline}", $col7)."\n";
	echo implode("", array_fill(0, 40, '--')) . "\n";
}

foreach ($departments as $department) {
    echo padRight($department->departmentName, $col1) .
         padLeft($department->personelAmount, $col2) . 
         padLeft($department->departmentSalary, $col3) . 
         padLeft($department->departmentCoffe, $col4) . 
         padLeft($department->departmentDocumentation, $col5) .
         padLeft($department->salaryPerPages, $col6) . "\n" ;
         
}   echo implode("", array_fill(0, 40, '--')) . "\n";

    echo padRight($company->average, $col1) .
         padLeft($company->averagePersonelAmount, $col2) . 
         padLeft($company->averageSalary, $col3) . 
         padLeft($company->averageCoffe, $col4) .
         padLeft($company->averageDocumentation, $col5) .
         padLeft($company->averageSalaryPerPages, $col6) . "\n";
         
    echo padRight($company->total, $col1) .
         padLeft($company->totalPersonelAmount, $col2) . 
         padLeft($company->totalSalary, $col3) . 
         padLeft($company->totalCoffe, $col4) .
         padLeft($company->totalDocumentation, $col5) .
         padLeft($company->totalSalaryPerPages, $col6)."\n\n";
}
printData($departments, $company, 0);
printData($departmentsCrysis1, $crysisCompany1, 1);
printData($departmentsCrysis2, $crysisCompany2, 2);
printData($departmentsCrysis3, $crysisCompany3, 3);