<?php
header("Content-Type: text/plain");
// ООП. Вектор и антикризичные меры
// Статический класс коофициентов для расчетов
class Coefficients
{
// Коофициенты зарплаты для ранга
static
private $xRankSalary = array (1 => '1', 2 => '1.25',
3 => '1.5');
// Коофициенты зарплаты для начальников
static
private $xChiefSalary = array (0 => '1', 1 => '1.5');
// Коофициенты потребления кофе для начальников
static
private $xChiefCoffee = array (0 => '1', 1 => '2');
// Коофициенты продуктивности для начальников
static
private $xChiefProduct = array (0 => '1', 1 => '0');
// Возвращаем коэф. зарплаты согласно рангу
static public function getXRankSalary ($rank)
{
return self::$xRankSalary[$rank];
}
// Возвращаем коэф. зарплаты шефа
static public function getXChiefSalary ($сhief)
{
return self::$xChiefSalary[$сhief];
}
// Возвращаем коэф. потребления кофе шефа
static public function getXChiefCoffee ($сhief)
{
return self::$xChiefCoffee[$сhief];
}
// Возвращаем коэф. производительности шефа
static public function getXChiefProduct ($сhief)
{
return self::$xChiefProduct[$сhief];
}
}
// Класс сотрудника
class Employee
{
private $rank = 1; // ранг
private $chief = 0; // статус руководителя
private $profession; // профессия
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 setRank ($rank)
{
$this->rank = $rank;
}
// Присвоение статуса начальник
public function setСhief ($chief)
{
$this->chief = $chief;
}
// Меням профессию
public function setProfession ($profession)
{
$this->profession = $profession;
}
// Возвращаем ранг сотрудника
public function getRank ()
{
return $this->rank;
}
// Возвращаем название профессии сотрудника
public function getProfessionName ()
{
return $this->profession->name;
}
// Возвращаем статус шафа сотрудника
public function getChief ()
{
return $this->chief;
}
// Расчет зарплаты
public function getSalary ()
{
// Профессия
$profession = $this->profession;
// Ставка по профессии
$salaryRate = $profession->getSalaryRate();
// Узнаем коэффициент согласно рангу сотрудника
$tmpxRank = Coefficients::getXRankSalary($this->rank);
// Узнаем коэффициент для начальника
$tmpxChiefSalary = Coefficients::getXChiefSalary($this->chief);
// Расчет зарплаты
$salary = $salaryRate * $tmpxRank * $tmpxChiefSalary;
return $salary;
}
// Расчет потребления кофе
public function getCoffee ()
{
// Профессия
$profession = $this->profession;
// Потребление кофе по профессии
$coffeeRate = $profession->getCoffeeRate();
// Вычисляем коэффициент для начальника
$tmpxChiefCoffee = Coefficients::getXChiefCoffee($this->chief);;
// Расчет потребления кофе
$coffee = $coffeeRate * $tmpxChiefCoffee;
return $coffee;
}
// Расчет продуктивности
public function getProduct ()
{
// Профессия
$profession = $this->profession;
// Продуктивность по профессии
$productRate = $profession->getProduct();
// Вычисляем коэффициент для начальника
$tmpxChiefProduct = Coefficients::getXChiefProduct($this->chief);;
// Расчет продуктивности
$product = $productRate * $tmpxChiefProduct;
return $product;
}
}
// Абстрактный класс профессии
abstract class Profession
{
public $name = ""; // название профессии
abstract public function getSalaryRate();
abstract public function getCoffeeRate();
abstract public function getProduct();
}
// Класс менджер
class Manager extends Profession
{
public $name = "Manager";
public function getSalaryRate()
{
return 500;
}
public function getCoffeeRate()
{
return 20;
}
public function getProduct()
{
return 200;
}
}
// Класс маркетолог
class Marketer extends Profession
{
public $name = "Marketer";
public function getSalaryRate()
{
return 500;
}
public function getCoffeeRate()
{
return 20;
}
public function getProduct()
{
return 200;
}
}
// Класс инженер
class Engineer extends Profession
{
public $name = "Engineer";
public function getSalaryRate()
{
return 200;
}
public function getCoffeeRate()
{
return 5;
}
public function getProduct()
{
return 50;
}
}
// Класс аналитик
class Analyst extends Profession
{
public $name = "Analyst";
public function getSalaryRate()
{
return 800;
}
public function getCoffeeRate()
{
return 50;
}
public function getProduct()
{
return 5;
}
}
// Класс аналитик
class NewAnalyst extends Profession
{
public $name = "Analyst";
public function getSalaryRate()
{
return 1100;
}
public function getCoffeeRate()
{
return 75;
}
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 = '')
{
$employeesNumber = 0; // число сотрудников
// Если считаем сотрудников определенной профессии
foreach ($this->employees as $employee) {
// Если сотрудник не соответствует профессии
if ($employee->getProfessionName() == $profession) {
continue;
}
// Счетчик
$employeesNumber++;
}
// Если профессия не задана
if ($profession == "") {
$employeesNumber = count($this->employees); }
return $employeesNumber;
}
// Возвращаем сотрудников массивом
public function getEmployees()
{
return $this->employees;
}
// Поиск сотрудника по профессии, рангу, статусу шефа
// параметр может принимать значение 'all', параметр будет игнорироваться
public function findEmployee ($profession, $rank, $chief)
{
$employee = null; // искомый Сотрудник
// Перебираем всех сотрудников
foreach ($this->employees as $employee) {
// Если сотрудник не соответствует профессии
if ($employee->getProfessionName() != $profession &&
$profession != 'all') {
continue;
}
// Если сотрудник не соответствует рангу
if ($employee->getRank() != $rank &&
$rank != 'all') {
continue;
}
// Если сотрудник не является начальником
if ($employee->getChief() != $chief &&
$chief != 'all') {
continue;
}
// Возвращаем Сотрудника
return $employee;
}
}
// Увольнение сотрудника
public function dismissEmployee($employee)
{
unset ($this->employees[$employeeKey]); }
// Расходы на зарплату
public function getTotalSalary ()
{
$totalSalary = 0; // сумарная зарплата
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем зп у сотрудника и суммируем результат
$totalSalary += $employee->getSalary ();
}
return $totalSalary;
}
// Рассход кофе
public function getTotalCoffee ()
{
$totalCoffee = 0; // сумарное потребление кофе
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем потребление кофе у сотрудника и суммируем результат
$totalCoffee += $employee->getCoffee ();
}
return $totalCoffee;
}
// Суммарная производительность
public function getTotalProduct ()
{
$totalProduct = 0; // сумарная продуктивность
// Для каждого сотрудника
foreach ($this->employees as $employee) {
// Запрашиваем продуктивность у сотрудника и суммируем результат
$totalProduct += $employee->getProduct ();
}
return $totalProduct;
}
// Средний расход тугриков на одну страницу
public function getAverageCostPerProduct ()
{
// Средняя стоимость 1 страницы = суммарная зарплата / сумарное количество страниц
$avrCostPerProduct = $this->getTotalSalary () / $this->getTotalProduct ();
return $avrCostPerProduct;
}
}
// Класс компании
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);
}
// Поиск департамента по названию, аргумент "all" возращает все департааменты
public function findDepartamentByName ($name = 'all')
{
$result = ""; // ссылка на департамент или массив департаментов
// Ищем департамент в массиве по названию
if ($name != 'all'){
$result = $this->departaments[$name];
}
// Возвращаем все департаменты массивом, если просят
if ($name == "all") {
foreach ($this->departaments as $name => $departament) {
$result[$name] = $departament;
}
}
// Если ничего не нашли
if ($result == null) {
// Ничего не возвращам, мы обиделись
die ("Департамент не найден"); }
return $result;
}
// Сумарное количество работников
public function getTotalEmployees ()
{
$totalEmployees = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем работников всех департаментов
$totalEmployees += $departament->countEmployees();
}
return $totalEmployees;
}
// Расходы на зарплату в сумме
public function getTotalSalary ()
{
$salary = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем зп всех департаментов
$salary += $departament->getTotalSalary();
}
return $salary;
}
// Рассход кофе в сумме
public function getTotalCoffee ()
{
$coffee = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Суммируем расход кофе у департаментов
$coffee += $departament->getTotalCoffee();
}
return $coffee;
}
// Суммарная производительность
public function getTotalProduct ()
{
$product = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Суммируем производительность каждого департамента
$product += $departament->getTotalProduct();;
}
return $product;
}
// Среднее количество работников по департаментам
public function getAverageEmployees ()
{
// Среднее количество работников = суммарное кол-во работников / кол-во департаментов
$avrEmployees = $this->getTotalEmployees () / count($this->departaments);
return $avrEmployees;
}
// Средняя зарплата по департаментам
public function getAverageSalary ()
{
// Средняя зарплата = суммарная зарплата / кол-во департаментов
$avrSalary = $this->getTotalSalary () / count($this->departaments);
return $avrSalary;
}
// Среднее потребление кофе по департаментам
public function getAverageCoffee ()
{
// Среднее потребление кофе = суммарная потребление кофе / кол-во департаментов
$avrCoffee = $this->getTotalCoffee () / count($this->departaments);
return $avrCoffee;
}
// Средняя производительность по департаментам
public function getAverageProduct ()
{
// Средняя производительность = суммарная производительность / кол-во департаментов
$avrProduct = $this->getTotalProduct () / count($this->departaments);
return $avrProduct;
}
// Средний расход тугриков на одну страницу по департаментам
public function getAverageCostPerProduct ()
{
$avrCostPerProduct = 0;
// Для каждого департамента
foreach ($this->departaments as $departament) {
// Сумируем средний расход
$avrCostPerProduct += $departament->getAverageCostPerProduct();
}
// Средняя стоимость 1 страницы = cредняя стоимость всех департ / кол-во департаментов
$avrCostPerProduct = $avrCostPerProduct / count($this->departaments);
return $avrCostPerProduct;
}
}
// Антикризисные меры 1
class AnticrisisFirst
{
/*
* Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров,
* преимущественно самого низкого ранга. Если инженер является боссом,
* вместо него надо уволить другого инженера, не босса.
* */
static public function dismissEngineers($company)
{
$companyClone = clone $company;
// Запрашивавем все департаменты в компании
$departaments = $companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Число всех инженеров
$engineersNumber = $departament->countEmployees("Engineer");
// Число уволенных мамкиных инженеров
$dismissedEngineers = 0;
// Процент уволенных инженеров
$procentDismissedEngineers = 0;
// Начинаем с первого ранга
$rank = 1;
// Нужно уволить 40%
while ($procentDismissedEngineers < 40 && $rank < 3 ) {
// Находим нужного инженера
$engineer = $departament->findEmployee("Engineer", $rank, 0);
//var_dump($engineer);
// Если не нашли нужного ранга
if ($engineer == null) {
// Увеличиваем ранг
$rank++;
// Повторяем цикл сначала
continue;
}
// Увольняем сотрудника
$departament->dismissEmployee($engineer);
// Число уволенных мамкиных инженеров
$dismissedEngineers++;
// Процент уволенных инженеров
$procentDismissedEngineers = $dismissedEngineers / $engineersNumber * 100;
}
}
// Выводим статистику на печать
printStatistics($companyClone, "Антикризисные меры 1");
}
}
/* Антикризисные меры 2
* Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков,
* а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах,
* где руководитель не является аналитиком, заменить его на аналитика
* самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
* */
class AnticrisisSecond
{
static public function increaseSalaryRate($company)
{
$companyClone = clone $company;
// Создаем новую профессию аналитика
$newAnalyst = new NewAnalyst;
// Запрашивавем все департаменты в компании
$departaments = $companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Запрашиваем работников
$employees = $departament->getEmployees();
// Перебираем работников
foreach($employees as $employee) {
// Если профессия аналитик
if ($employee->getProfessionName () == "Analyst") {
// Меняем профессию на новую
$employee->setProfession ($newAnalyst);
}
}
}
foreach ($departaments as $departamentName => $departament) {
// Находим шефа в компании
$chiefEmployee = $departament->findEmployee ("all", "all", 1);
// Узнаем профессию
$professionName = $chiefEmployee->getProfessionName();
// Находим аналитика самого высокого ранга
// Запрашиваем Аналитиков от 3 до 1 ранга, определяем самый высокй ранг
for ($rank = 3; $rank > 0; $rank--) {
// Запрашиваем Ааналитика из Департамента
$analyst = $departament->findEmployee ("Analyst", $rank, 0);
// Проверяем, вернул ли Департамент Аналитика нужного ранга
if ($analyst != null) {
// Назначаем Аналитика шефом
$analyst->setСhief(1);
// Снимаем с должности текущего шефа
$chiefEmployee->setСhief(0);
break;
}
}
}
// Выводим статистику на печать
printStatistics($companyClone, "Антикризисные меры 2");
}
}
/* Антикризисные меры 3
* В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга
* на один ранг с целью расширить их полномочия.
* */
class AnticrisisThird
{
static public function liftManager($company)
{
// Создаем новую компанию
$companyClone = clone $company;
// Запрашивавем все департаменты в компании
$departaments = $companyClone->findDepartamentByName();
// Перебираем все департаменты в компании
foreach ($departaments as $departamentName => $departament) {
// Запрашиваем всех работников
$employees = $departament->getEmployees ();
$managerNumber = 0; // Количество манагеров 1 и 2 ого ранга
$liftedManagerNumber = 0; // Количество повышенных манагеров 1 и 2 ого ранга
$liftedManagerProcent = 0; // % повышенных манагеров 1 и 2 ого ранга
// Перебираем всех сотрудников чтобы посчитать кол-во манагеров
foreach ($employees as $employee) {
$employeeProfessionName = $employee->getProfessionName();
$employeeRank = $employee->getRank();
if ($employeeProfessionName != "Manager") {
continue;
}
if ($employeeRank > 2) {
continue;
}
// Считаем менеджеров
$managerNumber++;
}
// Перебираем всех сотрудников, чтобы повысить манагеров 1 и 2 ранга
foreach ($employees as $employee) {
$employeeProfessionName = $employee->getProfessionName();
$employeeRank = $employee->getRank();
if ($employeeProfessionName != "Manager") {
continue;
}
if ($employeeRank > 2) {
continue;
}
// Повышаем манагера
$employee->setRank($employeeRank+1);
// Считаем
$liftedManagerNumber++;
$liftedManagerProcent = ($liftedManagerNumber / $managerNumber) * 100;
// Проверяем процент повышенных манагеров
if ($liftedManagerProcent > 50){
break;
}
}
}
printStatistics($companyClone, "Антикризисные меры 3");
}
}
// Функция создания компании
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];
// Достаем ранг из вакансии
// Достаем статус начальника из вакансии
$chief = ($chief==null)? 0 : 1; // если статус не определен явно, считаем что 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 padLeft($string, $length)
{
// Разница между переданной строкой и шириной колонки
$lenghtDifference = $length-mb_strlen($string); // Проверка на отрицательное значение при вычитании
if ($lenghtDifference >= 0) {
// Заполняем разницу пробелами
$string = str_repeat(" ", $lenghtDifference) . $string; } else {
// Если таки отрицательное, обрезаем край строки до ширины колонки
}
return $string;
}
// Добавление пробелов справа
private function padRight($string, $length)
{
// Разница между переданной строкой и шириной колонки
$lenghtDifference = $length-mb_strlen($string); // Проверка на отрицательное значение при вычитании
if ($lenghtDifference >= 0) {
// Заполняем разницу пробелами
} 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, "Докризисная статистика");
AnticrisisFirst::dismissEngineers($vector);
AnticrisisSecond::increaseSalaryRate($vector);
AnticrisisThird::liftManager($vector);
?>