<?php
class Employee
{
const FIRST_RANK = 1.0;
const SECOND_RANK = 1.25;
const THIRD_RANK = 1.5;
const BOSS_PREMIUM = 1.5;
const BOSS_COFFEE_PREMIUM = 2.0;
const BOSS_PAGES_MULTIPLIER = 0;
public $isBoss;
public $rank;
public $profession;
private static
$dependencies = array( 'manager'=>array('coffee'=>20, 'pages'=>200, 'wageRate'=>500), 'marketer'=>array('coffee'=>15, 'pages'=>150, 'wageRate'=>400), 'engineer'=>array('coffee'=>5, 'pages'=>50, 'wageRate'=>200), 'analyst'=>array('coffee'=>50, 'pages'=>5, 'wageRate'=>800), );
public function getDependencies()
{
return self::$dependencies;
}
public static
function updateDependencies
(array $dependencies) {
self::$dependencies = array_merge(self::$dependencies, $dependencies); }
private function getProfDependencies()
{
$allDependencies = $this->getDependencies();
return $allDependencies[$this->profession];
}
public function getCoffeeConsuming()
{
$profDependencies = $this->getProfDependencies($this->profession);
return ($this->isBoss) ? self::BOSS_COFFEE_PREMIUM * $profDependencies['coffee']
: $profDependencies['coffee'];
}
public function getSalary()
{
$profDependencies = $this->getProfDependencies($this->profession);
return ($this->isBoss) ? self::BOSS_PREMIUM * $profDependencies['wageRate'] * $this->rank
: $profDependencies['wageRate'] * $this->rank;
}
public function getPages()
{
$profDependencies = $this->getProfDependencies($this->profession);
return ($this->isBoss) ? self::BOSS_PAGES_MULTIPLIER * $profDependencies['pages']
: $profDependencies['pages'];
}
public function __construct($profession, $rank = 1, $isBoss = false)
{
$this->profession = $profession;
$this->rank = $rank;
$this->isBoss = $isBoss;
}
}
class Report
{
public $departmentName;
public $salary;
public $coffee;
public $pages;
public $employeeCount;
}
class Department
{
public $name;
public $employees = array();
public function __construct($name)
{
$this->name = $name;
}
public function getReport()
{
$report = new Report;
foreach ($this->employees as $employee) {
$report->salary += $employee->getSalary();
$report->coffee += $employee->getCoffeeConsuming();
$report->pages += $employee->getPages();
}
$report->departmentName = $this->name;
$report->employeeCount = count($this->employees); return $report;
}
public function hireEmployee(Employee $employee)
{
$this->employees[] = $employee;
}
public function fireEmployee(Employee $e)
{
foreach ($this->employees as $employee) {
if ($employee != $e) continue;
unset($this->employees[$index]); break;
}
}
public function fireMassive($profession, $amount)
{
$tolalCount = 0;
foreach ($this->employees as $employee) {
if ($employee->profession == $profession) $tolalCount += 1;
}
$fired = 0;
foreach ($this->employees as $employee) {
if ($employee->profession != $profession or $employee->isBoss) continue;
if ($fired == $toFire) break;
$this->fireEmployee($employee);
$fired++;
}
}
}
function hireCrowd(Department $dep, $number, $profession, $rank = 1, $isBoss = false) {
for ($i = 0; $i < $number; $i++) {
$employee = new Employee($profession, $rank, $isBoss);
$dep->hireEmployee($employee);
}
}
class Company
{
private $departments = array(); public function getDepartments()
{
return $this->departments;
}
public $name;
public function __construct($name)
{
$this->name = $name;
}
public function getReport()
{
foreach ($this->departments as $department) {
$report[] = $department->getReport();
}
return $report;
}
public function addDepartment(Department $department)
{
$this->departments[] = $department;
}
public function dismissDepartment(Department $dep)
{
foreach ($this->departments as $department) {
if ($department != $dep) continue;
break;
}
}
}
$procurement = new Department('Отдел закупок');
hireCrowd($procurement, 9, 'manager');
hireCrowd($procurement, 3, 'manager', Employee::SECOND_RANK);
hireCrowd($procurement, 2, 'manager', Employee::THIRD_RANK);
hireCrowd($procurement, 2, 'marketer');
hireCrowd($procurement, 1, 'manager', Employee::SECOND_RANK, true);
$selling = new Department('Отдел продаж');
hireCrowd($selling, 12, 'manager');
hireCrowd($selling, 6, 'marketer');
hireCrowd($selling, 3, 'analyst');
hireCrowd($selling, 2, 'analyst', Employee::SECOND_RANK);
hireCrowd($selling, 1, 'marketer', Employee::SECOND_RANK, true);
$advertisement = new Department('Отдел рекламы');
hireCrowd($advertisement, 15, 'marketer');
hireCrowd($advertisement, 10, 'marketer', Employee::SECOND_RANK);
hireCrowd($advertisement, 8, 'manager');
hireCrowd($advertisement, 2, 'engineer');
hireCrowd($advertisement, 1, 'marketer', Employee::THIRD_RANK, true);
$logistics = new Department('Отдел логистики');
hireCrowd($logistics, 13, 'manager');
hireCrowd($logistics, 5, 'manager', Employee::SECOND_RANK);
hireCrowd($logistics, 5, 'engineer');
hireCrowd($logistics, 1, 'manager', Employee::FIRST_RANK, true);
$vector = new Company('Вектор');
$vector->addDepartment($procurement);
$vector->addDepartment($selling);
$vector->addDepartment($advertisement);
$vector->addDepartment($logistics);
// Начальные условия
ViewHelper::printReport($vector);
// 1. Антикризисные меры: увольняю 40% инженеров во всех отделах
/*foreach ($vector->getDepartments() as $department) {
$department->fireMassive('engineer', 0.4);
}
ViewHelper::printReport($vector);*/
// 2. Антикризисные меры: меняю расходы на аналитиков, делаю аналитиков начальниками
// в тех департаментах, где они есть, иначе не меняю босса
Employee
::updateDependencies(array('analyst'=>array('wageRate'=>1100,'coffee'=>75,'pages'=>5)));foreach ($vector->getDepartments() as $department) {
foreach ($department->employees as $employee) {
if ($employee->isBoss) {
$oldBoss = $employee;
break;
}
}
if ($oldBoss->profession == 'analyst') continue;
$pretendent = null;
foreach ($department->employees as $employee) {
if ($employee->profession != 'analyst') continue;
if (!$pretendent or $pretendent->rank < $employee->rank) {
$pretendent = $employee;
}
}
if ($pretendent) {
$oldBossIndex = array_search($oldBoss, $department->employees); $department->employees[$oldBossIndex]->isBoss = false;
$pretendentIndex = array_search($pretendent, $department->employees); $department->employees[$pretendentIndex]->isBoss = true;
}
}
ViewHelper::printReport($vector);
class ViewHelper
{
public static function printReport(Company $company)
{
echo self::padRight('Департамент');
echo self::padLeft('сотр.');
echo self::padLeft('тугр.');
echo self::padLeft('кофе');
echo self::padLeft('стр.');
echo self::padLeft('тугр./стр.'), "\n";
for ($i=0; $i < 95; $i++) echo '-';
echo "\n";
$reports = $company->getReport();
foreach ($reports as $report) {
echo self::padRight($report->departmentName);
echo self::padLeft($report->employeeCount);
echo self::padLeft($report->salary);
echo self::padLeft($report->coffee);
echo self::padLeft($report->pages);
echo self::padLeft(round($report->salary / $report->pages, 1)); echo "\n";
}
echo self::padRight('Среднее');
echo self::padLeft(self::average($reports, 'employeeCount'));
echo self::padLeft(self::average($reports, 'salary'));
echo self::padLeft(self::average($reports, 'coffee'));
echo self::padLeft(self::average($reports, 'pages'));
echo "\n";
echo self::padRight('Всего');
echo self::padLeft(self::summary($reports, 'employeeCount'));
echo self::padLeft(self::summary($reports, 'salary'));
echo self::padLeft(self::summary($reports, 'coffee'));
echo self::padLeft(self::summary($reports, 'pages'));
echo "\n";
}
private static function summary($reports, $propertyName)
{
for ($i=0, $sum=0; $i < count($reports); $i++) { $sum += $reports[$i]->$propertyName;
}
return $sum;
}
private static function average($reports, $propertyName)
{
$sum = self::summary($reports, $propertyName);
}
private static function padRight($string, $columnSize=20) {
$paddingSize = $columnSize - mb_strlen($string); return $string;
}
private static function padLeft($string, $columnSize=15) {
$paddingSize = $columnSize - mb_strlen($string); $string = str_repeat(' ', $paddingSize) . $string; return $string;
}
}