<?php
//Убрал в функция createEmployee, padLeft, padRight - тайп-хинт
//Для int и string, т.к. ideone считает их за объекты
class Company
{
private $name;
private $listOfDepatments;
public function __construct($name)
{
$this->name = $name;
$this->listOfDepatments = array(); }
public function __clone()
{
$countDepartment = $this->getCountDeparments();
for ($i = 0; $i < $countDepartment; $i++) {
$this->listOfDepatments[$i] = clone $this->listOfDepatments[$i];
}
}
/**
* Метод возвращающий имя компании
*
* @return string Имя компании
*/
public function getNameCompany()
{
return $this->name;
}
/**
* Метод возвращающий количество департаментов
*
* @return integer Имя компании
*/
public function getCountDeparments()
{
return count($this->listOfDepatments); }
/**
* Метод добавляющий новый департамент в компанию
*
* @param Department $newDepartment Добавляемый департамент
* @return void
*/
public function addDepartmentToCompany(Department $newDepartment)
{
$this->listOfDepatments[] = $newDepartment;
}
/**
* Метод возвращающий список департаментов
*
* @return array Массив департаментов
*/
public function getListOfDepartments()
{
return $this->listOfDepatments;
}
}
class Department
{
private $name;
private $listOfEmployee;
public function __construct($name)
{
$this->name = $name;
$this->listOfEmployee = array(); }
public function __clone()
{
$countEmployee = $this->getCountEmployee();
for ($i = 0; $i < $countEmployee; $i++) {
$this->listOfEmployee[$i] = clone $this->listOfEmployee[$i];
}
}
/**
* Метод возвращающий имя департамента
*
* @return string Имя департамент
*/
public function getDepartmentName()
{
return $this->name;
}
/**
* Метод возвращающий список сотрудников
*
* @return array Список сотрудников
*/
public function getListOfEmployee()
{
return $this->listOfEmployee;
}
/**
* Метод изменяет список список
*
* @param array $listOfEmployee Новый список сотрудников
* @return void
*/
public function setListOfEmployee
(array $listOfEmployee) {
$this->listOfEmployee = $listOfEmployee;
}
/**
* Метод добавляющий нового сотрудника
*
* $param Employee $newEmployee Новый сотрудник
* @return void
*/
public function addEmployeeToDepartment(Employee $newEmployee)
{
$this->listOfEmployee[] = $newEmployee;
}
/**
* Метод возвращающий количество сотрудников
*
* @return integer Количество сотрудников
*/
public function getCountEmployee()
{
return count($this->listOfEmployee); }
/**
* Метод возвращающий зарплату всего департамента
*
* @return integer Зарплата департамента
*/
public function getTotalSalary()
{
$totalSalary = 0;
foreach ($this->listOfEmployee as $employee) {
$totalSalary += $employee->getSalary();
}
return $totalSalary;
}
/**
* Метод возвращающий общее число наработанных страниц
*
* @return integer Количество страниц
*/
public function getTotalPages()
{
$totalPages = 0;
foreach ($this->listOfEmployee as $employee) {
$totalPages += $employee->getPages();
}
return $totalPages;
}
/**
* Метод возвращающий общее число выпитых кружен
*
* @return integer Число выпитых кружек
*/
public function getTotalCups()
{
$totalCups = 0;
foreach ($this->listOfEmployee as $employee) {
$totalCups += $employee->getCupOfCoffee();
}
return $totalCups;
}
/**
* Метод возвращает количество инженеров в департаменте
*
* @return integer Количество инженеров
*/
public function totalEngineer()
{
$result = 0;
foreach ($this->listOfEmployee as $employee) {
if ($employee->checkProffession('Engineer')) {
$result++;
}
}
return $result;
}
/**
* Метод возвращает количество менеджеров в департаменте
*
* @return integer Количество менеджеров
*/
public function totalManager()
{
$result = 0;
foreach ($this->listOfEmployee as $employee) {
if ($employee->checkProffession('Manager')) {
$result++;
}
}
return $result;
}
/**
* Метод возвращает руководителя департамента, если он существует, либо NULL
*
* @return Employee Сотрудник руководитель департамента
*/
public function findDirector()
{
$director = NULL;
foreach ($this->listOfEmployee as $employee) {
if ($employee->isDirector) {
$director = $employee;
break;
}
}
return $director;
}
}
abstract class Employee
{
public $isDirector;
protected $rank;
protected $proffession;
protected $salary;
protected $pages;
protected $cupOfCoffee;
public function __construct($rank, $isDirector = false)
{
$this->rank = $rank;
$this->isDirector = $isDirector;
$this->setSalary();
$this->setPages();
$this->setCupOfCoffee();
$this->setProffession();
}
abstract public function setSalary();
abstract public function setPages();
abstract public function setCupOfCoffee();
abstract public function setProffession();
public function setRank($rank)
{
$this->rank = $rank;
}
/**
* Метод возвращающий профессию сотрудника
*
* @return string Профессия сотрудника
*/
public function getEmployeeProffession()
{
return $this->proffession;
}
/**
* Метод возвращающий ранг сотрудника
*
* @return integer Ранг сотрудника
*/
public function getEmployeeRank()
{
return $this->rank;
}
/**
* Метод возвращающий зарплату сотрудника
*
* @return integer Зарплата сотрудника
*/
public function getSalary()
{
$totalSalary = $this->salary;
if ($this->rank == 2) {
$totalSalary *= 1.25;
} elseif ($this->rank == 3) {
$totalSalary *= 1.5;
}
if ($this->isDirector) {
$totalSalary *= 1.5;
}
return $totalSalary;
}
/**
* Метод возвращающий количество наработанных страниц сотрудником
*
* @return integer Общее число страниц сотрудника
*/
public function getPages()
{
return ($this->isDirector ? 0 : $this->pages);
}
/**
* Метод возвращающий количество выпитых кружек сотрудником
*
* @return integer Количество выпитых кружек
*/
public function getCupOfCoffee()
{
return ($this->isDirector ? ($this->cupOfCoffee * 2) : $this->cupOfCoffee);
}
/**
* Метод проверяющий соответствие сотрудника заданной профессии
*
* @param string $proffession Заданная профессия
* @return boolean Соответствует ли сотрудник указанной профессии
*/
public function checkProffession($proffession) {
return (static::class == $proffession) ? true : false;
}
}
class Manager extends Employee
{
public function setSalary($salary = 500)
{
$this->salary = $salary;
}
public function setPages($pages = 200)
{
$this->pages = $pages;
}
public function setCupOfCoffee($cups = 20)
{
$this->cupOfCoffee = $cups;
}
public function setProffession()
{
$this->proffession = 'Менеджер';
}
}
class Marketer extends Employee
{
public function setSalary($salary = 400)
{
$this->salary = $salary;
}
public function setPages($pages = 150)
{
$this->pages = $pages;
}
public function setCupOfCoffee($cups = 15)
{
$this->cupOfCoffee = $cups;
}
public function setProffession()
{
$this->proffession = 'Маркетолог';
}
}
class Engineer extends Employee
{
public function setSalary($salary = 200)
{
$this->salary = $salary;
}
public function setPages()
{
$this->pages = 50;
}
public function setCupOfCoffee()
{
$this->cupOfCoffee = 5;
}
public function setProffession()
{
$this->proffession = 'Инженер';
}
}
class Analyst extends Employee
{
public function setSalary($salary = 800)
{
$this->salary = $salary;
}
public function setPages($pages = 5)
{
$this->pages = $pages;
}
public function setCupOfCoffee($cups = 50)
{
$this->cupOfCoffee = $cups;
}
public function setProffession()
{
$this->proffession = 'Аналитик';
}
}
class CrisisCommittee
{
/**
* Метод "отдающий приказ" на увольнение инженеров в каждом департаменте
*
* @param Company $company Компания, в которой идет сокращение
* @return void
*/
//Дать приказ на увольнение инженеров в каждом департаменте
public function reduceEngineer(Company $company)
{
$listOfDepatments = $company->getListOfDepartments();
foreach ($listOfDepatments as $departament) {
$this->reduceEngineerInDep($departament, 40);
}
}
/**
* Метод возвращающий список номеров сотрудников соответствующие указанной профессии
*
* @param array $listOfEmployee Список всех сотрудников
* @param string $proffession Профессия для фильтра
* @return array Список номеров нужных сотрудников
*/
public function getEmployeeByCondition
(array $listOfEmployee, $proffession) {
uasort($listOfEmployee, 'sortByRank'); $countEmployee = count($listOfEmployee);
for ($i = 0; $i < $countEmployee; $i++) {
if ($listOfEmployee[$i]->checkProffession($proffession) && (!$listOfEmployee[$i]->isDirector)) {
$result[] = $i;
}
}
return $result;
}
/**
* Метод увольнения инженеров с наименьшим рангов и не являющихся руководителями
*
* @param Department $departament Департамент, в котором происходит увольнение
* @return void
*/
public function reduceEngineerInDep(Department $departament)
{
$listOfEmployee = $departament->getListOfEmployee();
$listOfEngineers = $this->getEmployeeByCondition($listOfEmployee, 'Analyst');
$countEngineer = count($listOfEngineers); $engineerDelete = ceil(0.4 * $countEngineer); $listOfReduceEngineer = array_slice($listOfEngineers, 0, $engineerDelete);
foreach ($listOfReduceEngineer as $numberEngineer) {
unset($listOfEmployee[$numberEngineer]); }
$departament->setListOfEmployee($listOfEmployee);
}
/**
* Метод повышения зарплаты
*
* @param Department $departament Департамент, в котором происходит повышение
* @param string $proffession Профессия, которой повышают зарплату
* @return void
*/
public function raiseSalary(Department $departament, $proffession)
{
$listOfEmployee = $departament->getListOfEmployee();
foreach ($listOfEmployee as $employee) {
if ($employee->checkProffession($proffession)) {
$employee->setSalary(1100);
$employee->setCupOfCoffee(75);
}
}
}
/**
* Метод "отдающий приказ" на повышение зарплаты аналитикам и повышении их в должности
* (вторая антикризисная мера)
*
* @param Company $company Компания
* @return integer Количество выпитых кружек
*/
public function raiseAnalytics(Company $company)
{
$listOfDepatments = $company->getListOfDepartments();
foreach($listOfDepatments as $departament) {
$this->raiseSalary($departament, "Analyst");
$this->changeDirector($departament, "Analyst");
}
}
/**
* Метод поиска сотрудника с высшим рангом указанной профессии
*
* @param Department $departament Департамент, в котором идет поиск
* @param string $proffession Профессия для фильтра
* @return Employee | boolean
*/
public function findHighestRankInProffession(Department $departament, $proffession)
{
$rank = 0;
$listOfEmployee = $departament->getListOfEmployee();
foreach ($listOfEmployee as $employee) {
if (($employee->getEmployeeRank() > $rank) && ($employee->checkProffession($proffession))) {
$analytics = $employee;
$rank = $employee->getEmployeeRank();
}
}
return ($rank) ? $analytics : false;
}
/**
* Метод смены руководителя департамента
*
* @param Department $departament Департамент, в котором происходит смена
* @param string $proffession Указывает, какая профессия должна быть у нового руководителя
* @return void
*/
public function changeDirector(Department $departament, $proffession)
{
$director = $departament->findDirector();
if (!$director) {
echo "Не задан директор";
}
if (!$director->checkProffession('Analyst')) {
$highestAnalytics = $this->findHighestRankInProffession($departament, $proffession);
if ($highestAnalytics) {
$highestAnalytics->isDirector = true;
$director->isDirector = false;
}
}
}
/**
* Метод "отдающий приказ" на повышение менеджеров в каждом департаменте
* (третий антикризисный план)
*
* @param Company $company Компания, в которой идет повышение
* @return void
*/
public function raiseManager(Company $company)
{
$listOfDepatments = $company->getListOfDepartments();
foreach($listOfDepatments as $departament) {
$this->raiseManagerInDep($departament, 50);
}
}
/**
* Метод повышающий ранг $percent процентам менеджерам
*
* @param Department $departament Департамент, в котором идет повышение
* @param int $percent Процент менеджеров, которым повышается ранг
* @return void
*/
public function raiseManagerInDep(Department $departament, $percent)
{
$countEmployee = $departament->getCountEmployee();
$countManager = $departament->totalManager();
$managerRaise = ceil(0.5 * $countManager);
$listOfEmployee = $departament->getListOfEmployee();
for ($i = 0; $i < $countEmployee; $i++) {
if ($managerRaise == 0) {
break;
}
if ($listOfEmployee[$i]->checkProffession('Manager') && ($listOfEmployee[$i]->getEmployeeRank() != 3)) {
$oldRank = $listOfEmployee[$i]->getEmployeeRank();
$listOfEmployee[$i]->setRank($oldRank + 1);
$managerRaise--;
}
}
}
}
/**
* Класс для создания отчета по компании
*/
class CompanyReport
{
public function printInfoAboutCompany(Company $company, $mssg = '')
{
$countDepartment = $company->getCountDeparments();
$total = array('сотр' => 0, 'тугр' => 0, 'кофе' => 0, 'стр' => 0);
echo "\"{$company->getNameCompany()}\"\n";
echo "{$mssg}\n";
echo padRigth("Деп. ", LARGE_COL) . padLeft("сотр.", SMALL_COL) . padLeft("тугр.", MEDIUM_COL) .
padLeft("кофе", SMALL_COL) . padLeft("стр.", MEDIUM_COL) . padLeft("тугр./стр.", LARGE_COL) . "\n";
$listOfDepatments = $company->getListOfDepartments();
foreach ($listOfDepatments as $departament) {
echo padRigth($departament->getDepartmentName(), LARGE_COL) . padLeft($departament->getCountEmployee(), SMALL_COL) .
padLeft($departament->getTotalSalary(), MEDIUM_COL) . padLeft($departament->getTotalCups(), SMALL_COL) .
padLeft($departament->getTotalPages(), MEDIUM_COL) . padLeft($departament->getTotalSalary() / $departament->getTotalPages(), LARGE_COL) . "\n";
$total['сотр'] += $departament->getCountEmployee();
$total['тугр'] += $departament->getTotalSalary();
$total['кофе'] += $departament->getTotalCups();
$total['стр'] += $departament->getTotalPages();
}
echo padRigth('Среднее', LARGE_COL) . padLeft($total['сотр'] / $countDepartment, SMALL_COL) .
padLeft($total['тугр'] / $countDepartment, MEDIUM_COL) . padLeft($total['кофе'] / $countDepartment, SMALL_COL) .
padLeft($total['стр'] / $countDepartment, MEDIUM_COL) . padLeft(($total['тугр'] / $total['стр']) / $countDepartment, LARGE_COL) . "\n";
echo padRigth('Всего', LARGE_COL) . padLeft($total['сотр'], SMALL_COL) .
padLeft($total['тугр'], MEDIUM_COL) . padLeft($total['кофе'], SMALL_COL) .
padLeft($total['стр'], MEDIUM_COL) . padLeft($total['тугр'] / $total['стр'], LARGE_COL) . "\n";
}
}
function sortByRank($a, $b)
{
return ($a->getEmployeeRank() > $b->getEmployeeRank()) ? 1 : -1;
}
function padLeft($text, $length)
{
}
return $text;
}
function padRigth($text, $length) {
}
return $text;
}
/**
* Функция создания массива сотрудников
*
* @param string $message Строка вида:9xме1;3xмe2;2xмe3;2xмa1;1xмe2 (последний идет руководитель)
* @return array Список сотрудников
*/
function createEmployee($message)
{
$totalPeople = count($people);
for ($i = 0; $i < $totalPeople; $i++) {
preg_match('/([0-9]+)x([а-яё]+)([0-9])/iu', $people[$i], $matches);
$countEmployee = (int) $matches[1];
$proffession = $matches[2];
$rank = (int) $matches[3];
$isDirector = ($i == ($totalPeople - 1)) ? true : false;
for ($j = 0; $j < $countEmployee; $j++ ) {
switch ($proffession) {
case "ме": $employee[] = new Manager($rank, $isDirector);
break;
case "ма": $employee[] = new Marketer($rank, $isDirector);
break;
case "ан": $employee[] = new Analyst($rank, $isDirector);
break;
case "ин": $employee[] = new Engineer($rank, $isDirector);
break;
default: echo "Проверьте входные данные! {$proffession}";
}
}
}
return $employee;
}
/**
* Функция добавляет созданный список сотрудников в департамент
*
* @return void
*/
function addAllEmployeeToDepartment
(array $employee, Department
$departament) {
$totalEmployee = count($employee);
for ($i = 0; $i < $totalEmployee; $i++) {
$departament->addEmployeeToDepartment($employee[$i]);
}
}
function createCompany($procurementPeople, $salesPeople, $advertisingPeople, $logisticsPeople)
{
$vector = new Company('Вектор');
$procurementDepartment = new Department('закупок');
$vector->addDepartmentToCompany($procurementDepartment);
$salesDepartament = new Department('продаж');
$vector->addDepartmentToCompany($salesDepartament);
$advertisingDepartment = new Department('рекламы');
$vector->addDepartmentToCompany($advertisingDepartment);
$logisticsDepartament = new Department('логистики');
$vector->addDepartmentToCompany($logisticsDepartament);
$procurementEmployee = array(); $procurementEmployee = createEmployee($procurementPeople);
addAllEmployeeToDepartment($procurementEmployee, $procurementDepartment);
$salesEmployee = array(); $salesEmployee = createEmployee($salesPeople);
addAllEmployeeToDepartment($salesEmployee, $salesDepartament);
$advertisingEmployee = array(); $advertisingEmployee = createEmployee($advertisingPeople);
addAllEmployeeToDepartment($advertisingEmployee, $advertisingDepartment);
$logisticsEmployee = array(); $logisticsEmployee = createEmployee($logisticsPeople);
addAllEmployeeToDepartment($logisticsEmployee, $logisticsDepartament);
return $vector;
}
$vector = createCompany(
'9xме1;3xме2;2xме3;2xма1;1xме2',
'12xме1;6xма1;3xан1;2xан2;1xма2',
'15xма1;10xма2;8xме1;2xин1;1xма3',
'13xме1;5xме2;5xин1;1xме1');
$report = new CompanyReport();
$report->printInfoAboutCompany($vector, '[Без антикризисных мер]');
$crisisCommittee = new CrisisCommittee();
$vectorWithoutEngineer = clone $vector;
$crisisCommittee->reduceEngineer($vectorWithoutEngineer);
$report->printInfoAboutCompany($vectorWithoutEngineer, '[Первая антикризисная мера]');
$vectorRaiseAnalytics = clone $vector;
$crisisCommittee->raiseAnalytics($vectorRaiseAnalytics);
$report->printInfoAboutCompany($vectorRaiseAnalytics, '[Вторая антикризисная мера]');
$vectorRaiseManager = clone $vector;
$crisisCommittee->raiseManager($vectorRaiseManager);
$report->printInfoAboutCompany($vectorRaiseManager, '[Третья антикризисная мера]');
?>