<?php
/* Сотрудник */
abstract class Employee
{
private $rate;//начальный рейт
private $rateWithRank;//рейт расчитанный с рангом
private $litresOfCoffee;
private $pgsOfDocs;
private $rank;
private $boss;
private $litresOfCoffeeWR;//аналогично для кофе
private $pgsOfDocsWR;//аналогично для доков
public function __construct(int $rate, int $litresOfCoffee, int $pgsOfDocs, int $rank, bool $boss = false){
$this->rate = $rate;
$this->litresOfCoffee = $litresOfCoffee;
$this->pgsOfDocs = $pgsOfDocs;
$this->rank = $rank;
$this->boss = $boss;
$this->litresOfCoffeeWR = $this->litresOfCoffee;
$this->pgsOfDocsWR = $this->pgsOfDocs;
$this->setRateWithRank();
if ($this->boss) {
$this->setBossPrivelege();
}
}
/*получить начальные свойства сотрудника*/
public function getAllProperties(){
return [$this->rate, $this->litresOfCoffee, $this->pgsOfDocs, $this->rank, $this->boss];
}
/*сетеры и гетеры для всех свойств*/
public function getRate(){
return $this->rateWithRank;
}
public function setRate(int $rate){
$this->rate = $rate;
$this->setRateWithRank();
if ($this->boss) {
$this->setBossPrivelege();
}
}
public function getCoffee(){
return $this->litresOfCoffeeWR;
}
public function setCoffee(int $litresOfCoffee){
$this->litresOfCoffee = $litresOfCoffee;
if ($this->boss) {
$this->litresOfCoffeeWR = $this->litresOfCoffee * 2;
} else {
$this->litresOfCoffeeWR = $this->litresOfCoffee;
}
}
public function getRank(){
return $this->rank;
}
public function setRank(int $rank){
$this->rank = $rank;
$this->setRateWithRank();
if ($this->boss) {
$this->setBossPrivelege();
}
}
public function getPages(){
return $this->pgsOfDocsWR;
}
public function setPages(int $pagesOfDocs){
$this->pgsOfDocs = $pagesOfDocs;
}
public function isBoss(){
return $this->boss;
}
public function setBossStatus(bool $bossStatus){
$this->boss = $bossStatus;
if ($this->boss) {
$this->setBossPrivelege();
} else {
$this->setRateWithRank();
$this->litresOfCoffeeWR = $this->litresOfCoffee;
$this->pgsOfDocsWR = $this->pgsOfDocs;
}
}
private function setRateWithRank(){
switch ($this->rank) {
case 1:
$this->rateWithRank = $this->rate;
break;
case 2:
$this->rateWithRank = $this->rate * 1.25;
break;
case 3:
$this->rateWithRank = $this->rate * 1.50;
break;
}
}
private function setBossPrivelege(){
$this->rateWithRank = $this->rateWithRank * 1.50;
$this->litresOfCoffeeWR = $this->litresOfCoffee * 2;
$this->pgsOfDocsWR = 0;
}
}
/* Группа сотрудников хранит уникального сотр-ка в N кол-ве*/
class EmployeeGroup
{
private $numOfEmployees;
private $employeeType;
public function __construct(int $numOfEmployees, Employee $employeeType){
$this->numOfEmployees = $numOfEmployees;
$this->employeeType = $employeeType;
}
public function getEmployee(){
return [$this->numOfEmployees, $this->employeeType];
}
public function addEmployee($num = 1){
$this->numOfEmployees += $num;
}
public function removeEmployee(){
if ($this->numOfEmployees > 0) {
$this->numOfEmployees--;
}
}
}
/* Штат департамента хранит группы сотрудников*/
class DepartmentStaff
{
private $listOfEmployeeTypes;
public function __construct(EmployeeGroup ...$listOfEmployeeTypes){
$this->listOfEmployeeTypes = $listOfEmployeeTypes;
}
public function getEmployeeTypes(){
return $this->listOfEmployeeTypes;
}
public function addEmployeeType(EmployeeGroup $addedEmployee){
$this->listOfEmployeeTypes[] = $addedEmployee;
}
public function removeEmployeeType(EmployeeGroup $deletedEmployeeType){
foreach ($this->listOfEmployeeTypes as $key => $employeeType) {
if ($deletedEmployeeType == $employeeType) {
unset($this->listOfEmployeeTypes[$key]); }
}
}
}
class Manager extends Employee
{}
class Marketer extends Employee
{}
class Engineer extends Employee
{}
class Analyst extends Employee
{}
/* Департамент хранит штат и считает всякие штуки */
class Department
{
private $name;
private $employees;
public function __construct(string $name, DepartmentStaff $employees){
$this->name = $name;
$this->employees = $employees;
}
public function getDepartmentStaff(){
return $this->employees;
}
public function getNumOfEmployees(){
$numOfEmployees = 0;
$employees = $this->employees->getEmployeeTypes();
foreach ($employees as $employee) {
list($num, $position) = $employee->getEmployee(); $numOfEmployees += $num;
}
return $numOfEmployees;
}
public function getSalaryOfEmployees(){
$salaryOfEmployees = 0;
$employees = $this->employees->getEmployeeTypes();
foreach ($employees as $employee) {
list($num, $position) = $employee->getEmployee(); $salaryOfEmployees += $position->getRate() * $num;
}
return $salaryOfEmployees;
}
/* Удаляет сотрудника из штата - одного из группы, или всех(группу разом)*/
public function fireEmployee(Employee $deletedPosition, $all = false){
$employees = $this->employees->getEmployeeTypes();
foreach ($employees as $employee) {
list($num, $position) = $employee->getEmployee(); if ($position == $deletedPosition) {
if ($all) {
$this->employees->removeEmployeeType($employee);
} else {
$employee->removeEmployee();
list($num, $position) = $employee->getEmployee(); if ($num == 0) {
$this->employees->removeEmployeeType($employee);
}
}
}
}
}
/* Добавляет сотрудника(группу в штат)*/
public function addEmployee(int $num, Employee $position){
$this->employees->addEmployeeType(new EmployeeGroup($num, $position));
}
public function getDrunkCoffee(){
$drunkCoffee = 0;
$employees = $this->employees->getEmployeeTypes();
foreach ($employees as $employee) {
list($num, $position) = $employee->getEmployee(); $drunkCoffee += $position->getCoffee() * $num;
}
return $drunkCoffee;
}
public function getPagesOfDocs(){
$pagesOfDocs = 0;
$employees = $this->employees->getEmployeeTypes();
foreach ($employees as $employee) {
list($num, $position) = $employee->getEmployee(); $pagesOfDocs += $position->getPages() * $num;
}
return $pagesOfDocs;
}
public function getTugricsPerPage(){
return round(($this->getSalaryOfEmployees() / $this->getPagesOfDocs()), 1); }
public function getNameOfDept(){
return $this->name;
}
}
class Company
{
private $departments;
private $name;
public function __construct(string $name, Department ...$departments)
{
$this->name = $name;
$this->departments = $departments;
}
public function getNameOfCompany(){
return $this->name;
}
public function getDepartments(){
return $this->departments;
}
}
function padRight($string, $widthOfCol){
if ($lengthOfString < $widthOfCol) {
$formattedString = $string . str_repeat(" ", $widthOfCol - $lengthOfString); return $formattedString;
}
}
function padLeft($string, $widthOfCol){
if ($lengthOfString < $widthOfCol) {
$formattedString = str_repeat(" ", $widthOfCol - $lengthOfString) . $string; return $formattedString;
}
}
//существующие виды сотрудников в компании
$manager1 = new Manager(500, 20, 200, 1);
$manager2 = new Manager(500, 20, 200, 2);
$manager2boss = new Manager(500, 20, 200, 2, true);
$manager3 = new Manager(500, 20, 200, 3);
$marketer1 = new Marketer(400, 15, 150, 1);
$analyst1 = new Analyst(800, 50, 5, 1);
$analyst2 = new Analyst(800, 50, 5, 2);
$marketer2boss = new Marketer(400, 15, 150, 2, true);
$marketer2 = new Marketer(400, 15, 150, 2);
$engineer1 = new Engineer(200, 5, 50, 1);
$marketer3boss = new Marketer(400, 15, 150, 3, true);
$manager1boss = new Manager(500, 21, 200, 1, true);
//Группы сотрудников одного вида по департаментам
$procurementGroup1 = new EmployeeGroup(9, $manager1);
$procurementGroup2 = new EmployeeGroup(3, $manager2);
$procurementGroup3 = new EmployeeGroup(2, $manager3);
$procurementGroup4 = new EmployeeGroup(2, $marketer1);
$procurementGroup5 = new EmployeeGroup(1, $manager2boss);
$salesGroup1 = new EmployeeGroup(12, $manager1);
$salesGroup2 = new EmployeeGroup(6, $marketer1);
$salesGroup3 = new EmployeeGroup(3, $analyst1);
$salesGroup4 = new EmployeeGroup(2, $analyst2);
$salesGroup5 = new EmployeeGroup(1, $marketer2boss);
$advGroup1 = new EmployeeGroup(15, $marketer1);
$advGroup2 = new EmployeeGroup(10, $marketer2);
$advGroup3 = new EmployeeGroup(8, $manager1);
$advGroup4 = new EmployeeGroup(2, $engineer1);
$advGroup5 = new EmployeeGroup(1, $marketer3boss);
$logstcGroup1 = new EmployeeGroup(13, $manager1);
$logstcGroup2 = new EmployeeGroup(5, $manager2);
$logstcGroup3 = new EmployeeGroup(5, $engineer1);
$logstcGroup4 = new EmployeeGroup(1, $manager1boss);
//Штаты сотрудников по департаментам
$procurementStaff = new DepartmentStaff($procurementGroup1, $procurementGroup2, $procurementGroup3, $procurementGroup4, $procurementGroup5);
$salesStaff = new DepartmentStaff($salesGroup1, $salesGroup2, $salesGroup3, $salesGroup4, $salesGroup5);
$advStaff = new DepartmentStaff($advGroup1, $advGroup2, $advGroup3, $advGroup4, $advGroup5);
$logstcStaff = new DepartmentStaff($logstcGroup1, $logstcGroup2, $logstcGroup3, $logstcGroup4);
//Департаменты
$procurementDep = new Department("Закупок", $procurementStaff);
$salesDep = new Department("Продаж", $salesStaff);
$advDep = new Department("Рекламы", $advStaff);
$logstcDep = new Department("Логистики", $logstcStaff);
//Компания
$company = new Company("Вектор", $procurementDep, $salesDep, $advDep, $logstcDep);
//Вывод отчета
function displayReport(Company $company){
$col1 = 15;
$col2 = 10;
$col3 = 10;
$col4 = 10;
$col5 = 10;
$col6 = 12;
echo padRight("Департамент", $col1) .
padLeft("Сотр.", $col2) .
padLeft("Тугр.", $col3) .
padLeft("Кофе", $col4) .
padLeft("Стр.", $col5) .
padLeft("Тугр./стр.", $col6) . "\n\n";
$allEmployees = 0;
$allSalary = 0;
$allCoffee = 0;
$allPages = 0;
$allTugPerPgs = 0;
foreach ($company->getDepartments() as $department) {
echo padRight($department->getNameOfDept(), $col1) .
padLeft($department->getNumOfEmployees(), $col2) .
padLeft($department->getSalaryOfEmployees(), $col3) .
padLeft($department->getDrunkCoffee(), $col4) .
padLeft($department->getPagesOfDocs(), $col5) .
padLeft($department->getTugricsPerPage(), $col6) . "\n";
$allEmployees += $department->getNumOfEmployees();
$allSalary += $department->getSalaryOfEmployees();
$allCoffee += $department->getDrunkCoffee();
$allPages += $department->getPagesOfDocs();
$allTugPerPgs += $department->getTugricsPerPage();
}
$numOfDepartments = count($company->getDepartments());
echo padRight("Среднее", $col1) .
padLeft
(round(($allEmployees / $numOfDepartments),1), $col2) . padLeft
(round(($allSalary / $numOfDepartments), 1), $col3) . padLeft
(round(($allCoffee / $numOfDepartments), 1), $col4) . padLeft
(round(($allPages / $numOfDepartments), 1), $col5) . padLeft
(round(($allTugPerPgs / $numOfDepartments), 1), $col6) . "\n";
echo padRight("Всего", $col1) .
padLeft($allEmployees, $col2) .
padLeft($allSalary, $col3) .
padLeft($allCoffee, $col4) .
padLeft($allPages, $col5) .
padLeft($allTugPerPgs, $col6) . "\n\n";
}
//До введения мер
echo "До введения мер:\n";
displayReport($company);
//План 1
foreach ($company->getDepartments() as $department) {
$sortedEngs = [];
$numOfEng = 0;
$staff = $department->getDepartmentStaff();
$groups = $staff->getEmployeeTypes();
foreach ($groups as $group) { /*считаем и сохраняем инженеров*/
list($num, $position) = $group->getEmployee(); if (is_a($position, "Engineer") and
!($position->isBoss())) { $numOfEng += $num;
$sortedEngs[$position->getRank()] = $group;
}
}
$numOfFiredEng = round($numOfEng * 0.4); ksort($sortedEngs); /*отсортируем по рангу*/ if ($numOfFiredEng > 0) { /*увольняем сколько нужно*/
while (true) {
foreach ($sortedEngs as $group) {
list($num, $position) = $group->getEmployee(); if (!($position->isBoss())) {
$department->fireEmployee($position);
$numOfFiredEng--;
if ($numOfFiredEng == 0) {
break 2;
}
}
}
}
}
}
echo "План 1:\n";
displayReport($company);
//Вернем начальные значения
$advGroup4->addEmployee();
$logstcGroup3->addEmployee(2);
//План 2
foreach ($company->getDepartments() as $department) {
$staff = $department->getDepartmentStaff();
$groups = $staff->getEmployeeTypes();
foreach ($groups as $key=>$group) { /*Меняем зп и литры кофе аналитикам*/
list($num, $position) = $group->getEmployee(); if (is_a($position, "Analyst")) { $position->setRate(1100);
$position->setCoffee(75);
}
}
}
$analystBoss = null;
foreach ($company->getDepartments() as $department) {
$analysts = [];
$analystWasFinded = false;
$staff = $department->getDepartmentStaff();
$groups = $staff->getEmployeeTypes();
foreach ($groups as $key=>$group) { /*Сохраняем аналитиков*/
list($num, $position) = $group->getEmployee(); if (is_a($position, "Analyst")) { $analysts[$position->getRank()] = [$position, $group];
$analystWasFinded = true;
}
}
if ($analystWasFinded){ /*Если анал-ки были текущего босса делаем не боссом*/
foreach ($groups as $group) {
list($num, $position) = $group->getEmployee(); if ($position->isBoss()) {
$position->setBossStatus(false);
}
}
krsort($analysts);/*сортируем анал-ов по рангу*/ $department->fireEmployee($position);/*увольняем высшего и снова нанимаем уже как босса*/
list($rate, $litresOfCoffee, $pgsOfDocs, $rank) = $position->getAllProperties(); $analystBoss = new Analyst($rate, $litresOfCoffee, $pgsOfDocs, $rank, true);
$department->addEmployee(1, $analystBoss);
}
}
echo "План 2:\n";
displayReport($company);
//вернем начальные значения
$salesDep->fireEmployee($analystBoss);
$marketer2boss->setBossStatus(true);
$analyst1->setRate(800);
$analyst1->setCoffee(50);
$analyst2->setRate(800);
$analyst2->setCoffee(50);
$salesGroup4->addEmployee();
//План 3
$addedEmplGroups = [];
foreach ($company->getDepartments() as $department) {
$elevatedEmployees = [];
$numOfMan = 0;
$objectsWasCopied = false;
$staff = $department->getDepartmentStaff();
$groups = $staff->getEmployeeTypes();
foreach ($groups as $key=>$group) { /*Считаем мен-ов 1 2 ранга*/
list($num, $position) = $group->getEmployee(); if (is_a($position, "Manager")) { if ($position->getRank() == 1 or $position->getRank() == 2) {
$numOfMan += $num;
}
}
}
$numOfFiredMan = round($numOfMan * 0.5); $numOfNewMan = $numOfFiredMan;
$key = $numOfNewMan;
$addedEmplTypes = [];
if ($numOfMan > 0) {
while (true) { /*Уволим мен-ов 1 2 ранга и скопируем эти позиции*/
foreach ($groups as $group) {
list($num, $position) = $group->getEmployee(); if (is_a($position, "Manager")) { if ($position->getRank() == 1 or $position->getRank() == 2) {
if ($num == 0) {
continue;
}
if(!$objectsWasCopied){
$elevatedEmployees[] = new EmployeeGroup(0, $position);
}
$group->removeEmployee();
$numOfFiredMan--;
if ($numOfFiredMan == 0) {
break 2;
}
}
}
}
$objectsWasCopied = true;
}
/*скопированным группам добавим число сотрудников(уволенные = нанятые снова)*/
while (true) {
foreach ($elevatedEmployees as $employee) {
list($num, $position) = $employee->getEmployee(); if ($position->isBoss() and $num == 1) {
continue;
} else {
$employee->addEmployee();
$numOfNewMan--;
}
if ($numOfNewMan == 0) {
break 2;
}
}
}
/*Добавим в департамент эти группы увеличив им ранг*/
foreach ($elevatedEmployees as $employee) {
list($num, $position) = $employee->getEmployee(); list($rate, $litresOfCoffee, $pgsOfDocs, $rank, $boss) = $position->getAllProperties(); $position = new Manager($rate, $litresOfCoffee, $pgsOfDocs, ++$rank, $boss);
$addedEmplTypes[] = new EmployeeGroup($num, $position);
$department->addEmployee($num, $position);
}
}
$addedEmplGroups[$key] = $addedEmplTypes;
}
echo "План 3:\n";
displayReport($company);
//вернем обратно
$departments = $company->getDepartments();
foreach ($addedEmplGroups as $numOfAddedEmpls=>$addedGroups) {
if ($numOfAddedEmpls == 0) {
continue;
} else {
$department = current($departments); $staff = $department->getDepartmentStaff();
foreach ($addedGroups as $group) {
$staff->removeEmployeeType($group);
}
$groups = $staff->getEmployeeTypes();
while (true) {
foreach ($groups as $group) {
list($num, $position) = $group->getEmployee(); if (is_a($position, "Manager")) { if ($position->getRank() == 1 or $position->getRank() == 2) {
if ($position->isBoss() and $num == 1) {
continue;
} else {
$group->addEmployee();
$numOfAddedEmpls--;
}
if ($numOfAddedEmpls == 0) {
break 2;
}
}
}
}
}
$department = next($departments); }
}
//displayReport($company);