<?php
header("Content-Type: text/plain");
// ООП. Вектор и антикризичные меры
// Класс сотрудника
class Employee
{
private $rank = 1; // ранг
private $chief = 0; // статус руководителя
private $profession; // профессия
// Коофициенты зарплаты для ранга
private $rankSalary = array(1 => 1, 2 => 1.25,
3 => 1.5);
// Коофициенты зарплаты для начальников
private $chiefSalary = array(0 => 1, 1 => 1.5);
// Коофициенты потребления кофе для начальников
private $chiefCoffee = array(0 => 1, 1 => 2);
// Коофициенты продуктивности для начальников
private $chiefProduct = array(0 => 1, 1 => 0);
public function __construct($profession, $rank, $chief)
{
// Присвоение профессии сотруднику
$this->profession = $profession;
// Присвоение ранга сотруднику
$this->rank = $rank;
// Присвоение статуса начальник
$this->chief = $chief;
}
// Присвоение профессии сотруднику
public function addProfession(Profession $profession)
{
$this->profession = $profession;
}
// Присвоение ранга сотруднику
public function getRank()
{
return $this->rank;
}
// Присвоение статуса начальник
public function setRank($rank)
{
$this->rank = $rank;
}
// Изменение базовой ставки
public function setСhief($chief)
{
$this->chief = $chief;
}
// Изменение кол-во выпиваемого кофе
public function setSalaryRate($salary)
{
$this->profession->setSalaryRate($salary);
}
// Возвращаем ранг сотрудника
public function setCoffeeRate($coffee)
{
$this->profession->setCoffeeRate($coffee);
}
// Возвращаем название профессии сотрудника
public function getProfession()
{
return $this->profession;
}
// Возвращаем статус шафа сотрудника
public function getChief()
{
return $this->chief;
}
// Расчет зарплаты
public function getSalary()
{
// Профессия
$profession = $this->profession;
// Ставка по профессии
$salaryRate = $profession->getSalaryRate();
// Узнаем коэффициент согласно рангу сотрудника
$tmpxRank = $this->rankSalary[$this->rank];
// Узнаем коэффициент для начальника
$tmpchiefSalary = $this->chiefSalary[$this->chief];
// Расчет зарплаты
$salary = $salaryRate * $tmpxRank * $tmpchiefSalary;
return $salary;
}
// Расчет потребления кофе
public function getCoffee()
{
// Профессия
$profession = $this->profession;
// Потребление кофе по профессии
$coffeeRate = $profession->getCoffeeRate();
// Вычисляем коэффициент для начальника
$tmpchiefCoffee = $this->chiefCoffee[$this->chief];
// Расчет потребления кофе
$coffee = $coffeeRate * $tmpchiefCoffee;
return $coffee;
}
// Расчет продуктивности
public function getProduct()
{
// Профессия
$profession = $this->profession;
// Продуктивность по профессии
$productRate = $profession->getProduct();
// Вычисляем коэффициент для начальника
$tmpchiefProduct = $this->chiefProduct[$this->chief];
// Расчет продуктивности
$product = $productRate * $tmpchiefProduct;
return $product;
}
}
// Абстрактный класс профессии
abstract class Profession
{
protected $salaryRate; // базовая ставка
protected $coffeeRate; // кол-во выпиваемого кофе
// Изменение базовой ставки
public function getSalaryRate()
{
return $this->salaryRate;
}
// Изменение кол-во выпиваемого кофе
public function setSalaryRate($salary)
{
$this->salaryRate = $salary;
}
public function getCoffeeRate()
{
return $this->coffeeRate;
}
public function setCoffeeRate($coffee)
{
$this->coffeeRate = $coffee;
}
// Возвращает имя
public function getName()
{
}
abstract public function getProduct();
}
// Класс менджер
class Manager extends Profession
{
protected $salaryRate = 500; // базовая ставка
protected $coffeeRate = 20; // кол-во выпиваемого кофе
public function getProduct()
{
return 200;
}
}
// Класс маркетолог
class Marketer extends Profession
{
protected $salaryRate = 400; // базовая ставка
protected $coffeeRate = 15; // кол-во выпиваемого кофе
public function getProduct()
{
return 150;
}
}
// Класс инженер
class Engineer extends Profession
{
protected $salaryRate = 200; // базовая ставка
protected $coffeeRate = 5; // кол-во выпиваемого кофе
public function getProduct()
{
return 50;
}
}
// Класс аналитик
class Analyst extends Profession
{
protected $salaryRate = 800; // базовая ставка
protected $coffeeRate = 50; // кол-во выпиваемого кофе
public function getProduct()
{
return 5;
}
}
// Класс департамента
class Departament
{
public $name = ""; // название
private $employees = array(); // сотрудники
public function __construct($name)
{
$this->name = $name;
}
// Клонирование департамента
public function __clone()
{
$employeesClones = array(); // клоны работников
foreach ($this->employees as $employee) {
$employee = clone $employee;
$departamentsClones[] = $employee;
}
// Заменяем массив работников массивом клонов
$this->employees = $departamentsClones;
}
// Прием сотрудника на работу
public function addEmployee(Employee $employee)
{
$this->employees[] = $employee;
}
// Расчет количества сотрудников по профессии, не указанный параметр возвращает общее кол-во
public function countEmployees($profession = null)
{
$employeesNumber = 0; // число сотрудников
// Если профессия не задана
if (!$profession) {
return count($this->employees); }
// Если считаем сотрудников определенной профессии
foreach ($this->employees as $employee) {
// Если сотрудник не соответствует профессии
if ($employee->getProfession()->getName() != $profession) {
continue;
}
// Счетчик
$employeesNumber++;
}
return $employeesNumber;
}
// Возвращаем сотрудников массивом
public function getEmployees()
{
return $this->employees;
}
// Поиск сотрудника по профессии, рангу, статусу шефа
// параметр может принимать значение 'all', параметр будет игнорироваться
public function findEmployee($profession, $rank, $chief)
{
$employee = null; // искомый Сотрудник
// Перебираем всех сотрудников
foreach ($this->employees as $employee) {
// Если сотрудник не соответствует профессии
if ($employee->getProfession()->getName() != $profession &&
$profession != 'all'
) {
continue;
}
// Если сотрудник не соответствует рангу
if ($employee->getRank() != $rank &&
$rank != 'all'
) {
continue;
}
// Если сотрудник не является начальником
if ($employee->getChief() != $chief &&
$chief != 'all'
) {
continue;
}
// Возвращаем Сотрудника
return $employee;
}
}
// Возвращает сотрудников заданной профессии массивом
public function findEmployees($profession)
{
$employees = array(); // массив Сотрудников
// Перебираем всех сотрудников
foreach ($this->employees as $employee) {
// Если сотрудник соответствует профессии
if ($employee->getProfession()->getName() == $profession) {
$employees[] = $employee;
}
}
// Возвращаем Сотрудников
return $employees;
}
// Увольнение сотрудника
public function dismissEmployee($employee)
{
$employeeKey = array_search($employee, $this->employees, TRUE); unset ($this->employees[$employeeKey]); }
// Расходы на зарплату
public function getTotalCoffee()
{
$totalCoffee = 0; // сумарное потребление кофе
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем потребление кофе у сотрудника и суммируем результат
$totalCoffee += $employee->getCoffee();
}
return $totalCoffee;
}
// Рассход кофе
public function getAverageCostPerProduct()
{
// Средняя стоимость 1 страницы = суммарная зарплата / сумарное количество страниц
$avrCostPerProduct = $this->getTotalSalary() / $this->getTotalProduct();
return $avrCostPerProduct;
}
// Суммарная производительность
public function getTotalSalary()
{
$totalSalary = 0; // сумарная зарплата
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем зп у сотрудника и суммируем результат
$totalSalary += $employee->getSalary();
}
return $totalSalary;
}
// Средний расход тугриков на одну страницу
public function getTotalProduct()
{
$totalProduct = 0; // сумарная продуктивность
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем продуктивность у сотрудника и суммируем результат
$totalProduct += $employee->getProduct();
}
return $totalProduct;
}
}
// Класс компании
class Company
{
public $name = ""; // название
private $departaments = array(); // департаменты
public function __construct($name)
{
$this->name = $name;
}
// Клонирование компании
public function __clone()
{
$departamentsClones = array(); // клоны департаментов
foreach ($this->departaments as $departament) {
$departament = clone $departament;
$departamentsClones[] = $departament;
}
// Заменяем массив департаментов массивом клонов
$this->departaments = $departamentsClones;
}
// Создание департамента
public function createDepartament($name)
{
$this->departaments[$name] = new Departament ($name);
}
// Поиск департамента по названию,
// если название не определено, возращает все департааменты
public function findDepartamentByName($name = null)
{
$result; // ссылка на департамент или массив департаментов
// Ищем департамент в массиве по названию
if ($name) {
$result = $this->departaments[$name];
} else {
// Возвращаем все департаменты массивом
foreach ($this->departaments as $name => $departament) {
$result[$name] = $departament;
}
}
// Если ничего не нашли
if ($result == null) {
// Ничего не возвращам, выкидываем исключение
throw new Exception ( "Департамент не найден" ) ;
}
return $result;
}
// Сумарное количество работников
public function getAverageEmployees()
{
// Среднее количество работников = суммарное кол-во работников / кол-во департаментов
$avrEmployees = $this->getTotalEmployees() / count($this->departaments);
return $avrEmployees;
}
// Расходы на зарплату в сумме
public function getTotalEmployees()
{
$totalEmployees = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем работников всех департаментов
$totalEmployees += $departament->countEmployees();
}
return $totalEmployees;
}
// Рассход кофе в сумме
public function getAverageSalary()
{
// Средняя зарплата = суммарная зарплата / кол-во департаментов
$avrSalary = $this->getTotalSalary() / count($this->departaments);
return $avrSalary;
}
// Суммарная производительность
public function getTotalSalary()
{
$salary = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем зп всех департаментов
$salary += $departament->getTotalSalary();
}
return $salary;
}
// Среднее количество работников по департаментам
public function getAverageCoffee()
{
// Среднее потребление кофе = суммарная потребление кофе / кол-во департаментов
$avrCoffee = $this->getTotalCoffee() / count($this->departaments);
return $avrCoffee;
}
// Средняя зарплата по департаментам
public function getTotalCoffee()
{
$coffee = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Суммируем расход кофе у департаментов
$coffee += $departament->getTotalCoffee();
}
return $coffee;
}
// Среднее потребление кофе по департаментам
public function getAverageProduct()
{
// Средняя производительность = суммарная производительность / кол-во департаментов
$avrProduct = $this->getTotalProduct() / count($this->departaments);
return $avrProduct;
}
// Средняя производительность по департаментам
public function getTotalProduct()
{
$product = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Суммируем производительность каждого департамента
$product += $departament->getTotalProduct();;
}
return $product;
}
// Средний расход тугриков на одну страницу по департаментам
public function getAverageCostPerProduct()
{
$avrCostPerProduct = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем средний расход
$avrCostPerProduct += $departament->getAverageCostPerProduct();
}
// Средняя стоимость 1 страницы = cредняя стоимость всех департ / кол-во департаментов
$avrCostPerProduct = $avrCostPerProduct / count($this->departaments);
return $avrCostPerProduct;
}
}
// Антикризисный коммитет
class AnticrisisCommittee
{
// Сожержит клон компании, к которому применяются АМ
private $companyClone;
// Клонирует компанию
public function cloneCompany($company)
{
$this->companyClone = clone $company;
}
/*
* Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров,
* преимущественно самого низкого ранга. Если инженер является боссом,
* вместо него надо уволить другого инженера, не босса.
* */
public function dismissEngineers()
{
// Запрашивавем все департаменты в компании
$departaments = $this->companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Берем всех работников определенной профессии
$engineers = $departament->findEmployees("Engineer");
// Если таковых нет, переходим к следующему департаменту
if (!$engineers) continue;
// Исключаем из списка босса
foreach ($engineers as $key => $engineer) {
if ($engineer->getChief() == 1) {
}
}
// Сортируем массив работников по рангу по возрастанию
// Внешний цикл повторяется до тех пор,
// пока во внутреннем цикле не будет перестановок
$isSort = false; // массив не отсортирован
while (!$isSort) {
$isSort = true; // Считаем, что массив отсортирован, и перестановок не будет
// Перебираем массив старым добрым for
for ($i = 0; $i < (count($engineers) - 1); $i++) { // Ранги первого и следующего в массиве работника
$rank1 = $engineers[$i]->getRank();
$rank2 = $engineers[$i++]->getRank();
// Сравниваем ранги работников попарно.
// Если ранг первого работника больше ранга следующего работника
// их нужно поменять местами
if ($rank1 > $rank2) {
// Меняем местами работников в массиве
$tmp = $engineers[$i++];
$engineers[$i++] = $engineers[$i];
$engineers[$i] = $tmp;
// Массив не отсортирован, т.к. была перестановка
$isSort = false;
}
}
}
// Берем первые 40% через array_slice
$dismissingEngineers = ceil(count($engineers) * 0.4); $engineers = array_slice($engineers, $dismissingEngineers);
// Увольняем сотрудников
foreach ($engineers as $engineer) {
$departament->dismissEmployee($engineer);
}
}
}
/*
* Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков,
* а количество выпиваемого им кофе с 50 до 75 литров.
* */
public function increaseSalaryRate()
{
// Запрашивавем все департаменты в компании
$departaments = $this->companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Запрашиваем работников
$analysts = $departament->findEmployees("Analyst");
// Если таковых нет, переходим к следующему департаменту
if (!$analysts) continue;
// Перебираем $analysts
foreach ($analysts as $analyst) {
// Повышаем ставку
$analyst->setSalaryRate(1100);
// Повышаем количество выпиваемого им кофе
$analyst->setCoffeeRate(75);
}
}
}
/*
* В тех департаментах, где руководитель не является аналитиком,
* заменить его на аналитика самого высшего ранга из этого департамента
* (а бывшего руководителя вернуть к обычной работе)
* */
public function setAnalystAsChief()
{
// Запрашивавем все департаменты в компании
$departaments = $this->companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Находим шефа в компании
$chiefEmployee = $departament->findEmployee("all", "all", 1);
// Узнаем профессию
$professionName = $chiefEmployee->getProfession()->getName();
// Если профессия не Аналитик, начинаем переназначение
if ($professionName != "Analyst") {
// Находим аналитика самого высокого ранга
// Повторяем для всех рангов, начиная с самого высокого
for ($rank = 3; $rank > 0; $rank--) {
// Запрашиваем Ааналитика из Департамента текущего ранга
// Т.к. мы начинаем с самого высокого ранга, то
// первый Аналитик, которого мы найдем,
// будет иметь самый высокий ранг в департаменте
$analyst = $departament->findEmployee("Analyst", $rank, 0);
// Проверяем, вернул ли Департамент Аналитика
if ($analyst != null) {
// Назначаем Аналитика шефом
$analyst->setСhief(1);
// Снимаем с должности текущего шефа
$chiefEmployee->setСhief(0);
break; // танцуем
}
}
}
}
}
/*
* В каждом департаменте повысить 50% (округляя в большую сторону)
* менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
* */
public function liftManager()
{
// Запрашивавем все департаменты в компании
$departaments = $this->companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Берем всех работников определенной профессии
$employees = $departament->findEmployees("Manager");
// Если таковых нет, переходим к следующему департаменту
if (!$employees) continue;
// Исключаем из списка менеджеров вышые 2ого ранга
foreach ($employees as $key => $employee) {
if ($employee->getRank() > 2) {
}
}
// Берем 50% через array_slice
$enhancingEmployees = ceil(count($employees) * 0.5); $employees = array_slice($employees, $enhancingEmployees);
// Повышаем сотрудников
foreach ($employees as $employee) {
$currentRank = $employee->getRank();
$employee->setRank($currentRank + 1);
}
}
}
// Выводим статистику на печать
public function printStat($message)
{
printStatistics($this->companyClone, $message);
}
}
// Функция создания компании
function createCompany($name)
{
// Создаем новый класс компании
$vector = new Company('$name');
// Создаем классы департаментов
$vector->createDepartament('Департамент закупок');
$vector->createDepartament('Департамент продаж');
$vector->createDepartament('Департамент рекламы');
$vector->createDepartament('Департамент логистики');
// Создаем классы профессий
$me = new Manager();
$ma = new Marketer();
$en = new Engineer();
$an = new Analyst();
// Добавляем профессии в масив для последующего создания сотрудников пачкой
$professions['me'] = $me;
$professions['ma'] = $ma;
$professions['en'] = $en;
$professions['an'] = $an;
// Лист вакансий: департамент => группы вакансий: профессияРанг статус_начальника => кол-во
'Департамент закупок' => array('me1' => '9', 'me2' => '3', 'me3' => '2', 'ma1' => '2', 'me2 1' => '1'), 'Департамент продаж' => array('me1' => '12', 'ma1' => '6', 'an1' => '3', 'an2' => '2', 'ma2 1' => '1'), 'Департамент рекламы' => array('ma1' => '15', 'ma2' => '10', 'me1' => '8', 'en1' => '2', 'ma3 1' => '1'), 'Департамент логистики' => array('me1' => '13', 'me2' => '5', 'en1' => '5', 'me1 1' => '1') );
// Для каждого департамента
foreach ($vacancies as $depName => $vacancyGroup) {
// Для каждой группы вакансий
foreach ($vacancyGroup as $vacancyName => $vacancyQuantity) {
// Достаем название профессии из вакансии
$professionIndex = mb_substr($vacancyName, 0, 2); $profession = $professions[$professionIndex];
// Достаем ранг и из вакансии
$rank = $matches1[0];
// Достаем статус начальника из вакансии
if(preg_match ('/ \d/', $vacancyName, $matches2)) { $chief = trim($matches2[0]); } else {
$chief = 0;
}
// Создаем столько сотрудников, сколько вакансий в группе
for ($id = 1; $id <= $vacancyQuantity; $id++) {
// Создаем сотрудника
$employee = new Employee($profession, $rank, $chief);
// Запрашиваем в Компании нужный департамент
$departament = $vector->findDepartamentByName($depName);
// Добавляем сотрудника в этот Департамент
$departament->addEmployee($employee);
}
}
}
// Возвращаем объект Компания
return $vector;
}
// Класс строки таблицы, хранит не фарматированную строку
class TableRow
{
private $columns = array(); // строка это массив из колонок
// Конструктор принимает массив колонок
public function __construct($columns)
{
$this->columns = $columns;
}
// Метод возвращает содержимое строки (все ее колоночки)
public function getColumns()
{
return $this->columns;
}
}
// Класс таблицы
class Table
{
private $tableRows = array(); // массив объектов Строк private $length = 15; // ширина колонок
// Добавление строки в таблицу, принимает массив
public function addRow($row)
{
// Создаем новую строку
$this->tableRows[] = new TableRow($row);
}
// Печать таблицы
public function printTable()
{
$caption = 1; // первая строка - заголовок таблицы
// Перебираем массив объектов Строк
foreach ($this->tableRows as $row) {
$stringRow = ""; // строка для печати
$columnNumber = 0; // счетчик колонок
// Извлекаем колонки из строки
$columns = $row->getColumns();
// Форматируем каждую колонку в строке
foreach ($columns as $column) {
// Округляем числа до 2х знаков после запятой
$column = round($column, 2); }
// Добавляем отступы справа для первой колонки
if ($columnNumber == 0) {
$stringRow .= "\n" . $this->padRight($column, $this->length);
// Добавляем оступы слева для остальных колонок
} else {
$stringRow .= $this->padLeft($column, $this->length);
}
$columnNumber++;
}
// Добавляем черту после заголовка
if ($caption == 1) {
$stringRow .= "\n" . $this->formatCaption($columnNumber, $this->length);
}
// Выводим строку на печать
echo "{$stringRow}";
$caption--; // останется только один заголовок
}
}
// Добавление пробелов слева
private function padRight($string, $length)
{
// Разница между переданной строкой и шириной колонки
$lenghtDifference = $length - mb_strlen($string); // Проверка на отрицательное значение при вычитании
if ($lenghtDifference >= 0) {
// Заполняем разницу пробелами
} else {
// Если таки отрицательное, обрезаем край строки до ширины колонки
}
return $string;
}
// Добавление пробелов справа
private function padLeft($string, $length)
{
// Разница между переданной строкой и шириной колонки
$lenghtDifference = $length - mb_strlen($string); // Проверка на отрицательное значение при вычитании
if ($lenghtDifference >= 0) {
// Заполняем разницу пробелами
$string = str_repeat(" ", $lenghtDifference) . $string; } else {
// Если таки отрицательное, обрезаем край строки до ширины колонки
}
return $string;
}
// Делаем горизонтальную черту
private function formatCaption($columnNumber, $length)
{
$string = str_repeat("-", $length * $columnNumber); return $string;
}
}
/* Вывод таблицы результатов */
// Функция вывода статистики по компании
function printStatistics($company, $caption)
{
// Создаем таблицу
$table = new Table();
// Заголовок таблицы
$table->addRow(array("Департамент", "сотр.",
"тугр.",
"кофе",
"стр.",
"тугр./стр.."));
// Статистика по департаентам
$departaments = $company->findDepartamentByName();
// Каждый департамент строка
foreach ($departaments as $departament) {
unset($columns); // обнуляем массив // Заполняем массив строк
$columns[] = $departament->countEmployees();
$columns[] = $departament->getTotalSalary();
$columns[] = $departament->getTotalCoffee();
$columns[] = $departament->getTotalProduct();
$columns[] = $departament->getAverageCostPerProduct();
// Добавляем строку в таблицу
$table->addRow($columns);
}
// Пустая строка
unset($columns); // обнуляем массив $columns[] = ' ';
// Добавляем строку в таблицу
$table->addRow($columns);
// Среднее для всей компании
unset($columns); // обнуляем массив // Заполняем массив строк
$columns[] = 'Среднее';
$columns[] = $company->getAverageEmployees();
$columns[] = $company->getAverageSalary();
$columns[] = $company->getAverageCoffee();
$columns[] = $company->getAverageProduct();
$columns[] = $company->getAverageCostPerProduct();
// Добавляем строку в таблицу
$table->addRow($columns);
// Всего для всей компании
unset($columns); // обнуляем массив // Заполняем массив строк
$columns[] = 'Всего';
$columns[] = $company->getTotalEmployees();
$columns[] = $company->getTotalSalary();
$columns[] = $company->getTotalCoffee();
$columns[] = $company->getTotalProduct();
// Добавляdем строку в таблицу
$table->addRow($columns);
// Выводим на печать заголовок
echo "{$caption}\n";
// Выводим таблицу на печать
$table->printTable();
echo "\n\n";
}
// Регистрируем Vector Inc на Сейшельских островах
$vector = createCompany('Vector');
printStatistics($vector, "Докризисная статистика");
// Создаем антикризисный коммитет
$anticrisisCommittee = new AnticrisisCommittee();
// Первый набор Антикризисных мер
$anticrisisCommittee->cloneCompany($vector);
$anticrisisCommittee->dismissEngineers();
$anticrisisCommittee->printStat("Антикризисные меры 1");
// Второй набор Антикризисных мер
$anticrisisCommittee->cloneCompany($vector);
$anticrisisCommittee->increaseSalaryRate();
$anticrisisCommittee->setAnalystAsChief();
$anticrisisCommittee->printStat("Антикризисные меры 2");
// Третий набор Антикризисных мер
$anticrisisCommittee->cloneCompany($vector);
$anticrisisCommittee->liftManager();
$anticrisisCommittee->printStat("Антикризисные меры 3");
?>