fork download
  1. <?php
  2.  
  3. ini_set('display_errors', 'on');
  4.  
  5.  
  6.  
  7. class Employee
  8. {
  9. const RANK_FIRST = 1.0;
  10. const RANK_SECOND = 1.25;
  11. const RANK_THIRD = 1.5;
  12. const BOSS_PREMIUM = 1.5;
  13. const BOSS_COFFEE_PREMIUM = 2.0;
  14. const BOSS_PAGES_MULTIPLIER = 0;
  15. const PROF_ENGINEER = 'engineer';
  16. const PROF_MANAGER = 'manager';
  17. const PROF_ANALYST = 'analyst';
  18. const PROF_MARKETER = 'marketer';
  19.  
  20. public $isBoss;
  21. public $rank;
  22. public $profession;
  23. public $baseCoffee;
  24. public $basePages;
  25. public $wageRate;
  26.  
  27. public function getSalary()
  28. {
  29. if ($this->isBoss)
  30. return self::BOSS_PREMIUM * $this->wageRate * $this->rank;
  31. else return $this->wageRate * $this->rank;
  32. }
  33.  
  34. public function setWageRate($wageRate)
  35. {
  36. $this->wageRate = $wageRate;
  37. }
  38.  
  39. public function getPages()
  40. {
  41. if ($this->isBoss) return self::BOSS_PAGES_MULTIPLIER * $this->basePages;
  42. return $this->basePages;
  43. }
  44.  
  45. public function setBasePages($pages)
  46. {
  47. $this->basePages = $pages;
  48. }
  49.  
  50. public function getCoffee()
  51. {
  52. if ($this->isBoss) return self::BOSS_COFFEE_PREMIUM * $this->baseCoffee;
  53. return $this->baseCoffee;
  54. }
  55.  
  56. public function setBaseCoffee($coffee)
  57. {
  58. $this->baseCoffee = $coffee;
  59. }
  60.  
  61. public function __construct($profession, $rank = 1, $isBoss = false)
  62. {
  63. $this->profession = $profession;
  64. $this->rank = $rank;
  65. $this->isBoss = $isBoss;
  66.  
  67. switch ($profession) {
  68. case Employee::PROF_MANAGER :
  69. $this->baseCoffee = 20;
  70. $this->basePages = 200;
  71. $this->wageRate = 500;
  72. break;
  73. case Employee::PROF_MARKETER :
  74. $this->baseCoffee = 15;
  75. $this->basePages = 150;
  76. $this->wageRate = 400;
  77. break;
  78. case Employee::PROF_ANALYST :
  79. $this->baseCoffee = 50;
  80. $this->basePages = 5;
  81. $this->wageRate = 800;
  82. break;
  83. case Employee::PROF_ENGINEER :
  84. $this->baseCoffee = 5;
  85. $this->basePages = 50;
  86. $this->wageRate = 200;
  87. break;
  88. default:
  89. throw new Exception('Неизвестная профессия');
  90. }
  91. }
  92. }
  93.  
  94. class Report
  95. {
  96. public $departmentName;
  97. public $salary;
  98. public $coffee;
  99. public $pages;
  100. public $employeeCount;
  101. }
  102.  
  103. class Department
  104. {
  105. public $name;
  106. public $employees = array();
  107.  
  108. public function __construct($name)
  109. {
  110. $this->name = $name;
  111. }
  112.  
  113. public function getReport()
  114. {
  115. $report = new Report;
  116. foreach ($this->employees as $employee) {
  117. $report->salary += $employee->getSalary();
  118. $report->coffee += $employee->getCoffee();
  119. $report->pages += $employee->getPages();
  120. }
  121. $report->departmentName = $this->name;
  122. $report->employeeCount = count($this->employees);
  123. return $report;
  124. }
  125.  
  126. public function hireEmployee(Employee $employee)
  127. {
  128. $this->employees[] = $employee;
  129. }
  130.  
  131. public function fireEmployee(Employee $e)
  132. {
  133. foreach ($this->employees as $employee) {
  134. if ($employee != $e) continue;
  135. $index = array_search($employee, $this->employees);
  136. unset($this->employees[$index]);
  137. break;
  138. }
  139. }
  140. }
  141.  
  142. function hireCrowd(Department $dep, $number, $profession, $rank = 1, $isBoss = false) {
  143. for ($i = 0; $i < $number; $i++) {
  144. $employee = new Employee($profession, $rank, $isBoss);
  145. $dep->hireEmployee($employee);
  146. }
  147. }
  148.  
  149. class Company
  150. {
  151. public $departments = array();
  152. public function getDepartments()
  153. {
  154. return $this->departments;
  155. }
  156.  
  157. public $name;
  158.  
  159. public function __construct($name)
  160. {
  161. $this->name = $name;
  162. }
  163.  
  164. public function getReport()
  165. {
  166. $report = array();
  167. foreach ($this->departments as $department) {
  168. $report[] = $department->getReport();
  169. }
  170. return $report;
  171. }
  172.  
  173. public function addDepartment(Department $department)
  174. {
  175. $this->departments[] = $department;
  176. }
  177.  
  178. public function dismissDepartment(Department $dep)
  179. {
  180. foreach ($this->departments as $department) {
  181. if ($department != $dep) continue;
  182. unset($department);
  183. break;
  184. }
  185. }
  186. }
  187.  
  188. class ViewHelper
  189. {
  190. public static function printReport(Company $company)
  191. {
  192. echo self::padRight('Департамент');
  193. echo self::padLeft('сотр.');
  194. echo self::padLeft('тугр.');
  195. echo self::padLeft('кофе');
  196. echo self::padLeft('стр.');
  197. echo self::padLeft('тугр./стр.'), "\n";
  198. for ($i=0; $i < 95; $i++) echo '-';
  199. echo "\n";
  200. $reports = $company->getReport();
  201. foreach ($reports as $report) {
  202. echo self::padRight($report->departmentName);
  203. echo self::padLeft($report->employeeCount);
  204. echo self::padLeft($report->salary);
  205. echo self::padLeft($report->coffee);
  206. echo self::padLeft($report->pages);
  207. echo self::padLeft(round($report->salary / $report->pages, 1));
  208. echo "\n";
  209. }
  210. echo self::padRight('Среднее');
  211. echo self::padLeft(self::average($reports, 'employeeCount'));
  212. echo self::padLeft(self::average($reports, 'salary'));
  213. echo self::padLeft(self::average($reports, 'coffee'));
  214. echo self::padLeft(self::average($reports, 'pages'));
  215. echo "\n";
  216. echo self::padRight('Всего');
  217. echo self::padLeft(self::summary($reports, 'employeeCount'));
  218. echo self::padLeft(self::summary($reports, 'salary'));
  219. echo self::padLeft(self::summary($reports, 'coffee'));
  220. echo self::padLeft(self::summary($reports, 'pages'));
  221. echo "\n";
  222. }
  223.  
  224. private static function summary($reports, $propertyName)
  225. {
  226. if (!is_array($reports) || count($reports) == 0) return 0;
  227. for ($i=0, $sum=0; $i < count($reports); $i++) {
  228. $sum += $reports[$i]->$propertyName;
  229. }
  230. return $sum;
  231. }
  232.  
  233. private static function average($reports, $propertyName)
  234. {
  235. $sum = self::summary($reports, $propertyName);
  236. return round($sum / count($reports), 1);
  237. }
  238.  
  239. private static function padRight($string, $columnSize=20) {
  240. $paddingSize = $columnSize - mb_strlen($string);
  241. $string .= str_repeat(' ', $paddingSize);
  242. return $string;
  243. }
  244.  
  245. private static function padLeft($string, $columnSize=15) {
  246. $paddingSize = $columnSize - mb_strlen($string);
  247. $string = str_repeat(' ', $paddingSize) . $string;
  248. return $string;
  249. }
  250. }
  251.  
  252.  
  253. $procurement = new Department('Отдел закупок');
  254. hireCrowd($procurement, 9, Employee::PROF_MANAGER);
  255. hireCrowd($procurement, 3, Employee::PROF_MANAGER, Employee::RANK_SECOND);
  256. hireCrowd($procurement, 2, Employee::PROF_MANAGER, Employee::RANK_THIRD);
  257. hireCrowd($procurement, 2, Employee::PROF_MARKETER);
  258. hireCrowd($procurement, 1, Employee::PROF_MANAGER, Employee::RANK_SECOND, true);
  259.  
  260. $selling = new Department('Отдел продаж');
  261. hireCrowd($selling, 12, Employee::PROF_MANAGER);
  262. hireCrowd($selling, 6, Employee::PROF_MARKETER);
  263. hireCrowd($selling, 3, Employee::PROF_ANALYST);
  264. hireCrowd($selling, 2, Employee::PROF_ANALYST, Employee::RANK_SECOND);
  265. hireCrowd($selling, 1, Employee::PROF_MARKETER, Employee::RANK_SECOND, true);
  266.  
  267. $advertisement = new Department('Отдел рекламы');
  268. hireCrowd($advertisement, 15, Employee::PROF_MARKETER);
  269. hireCrowd($advertisement, 10, Employee::PROF_MARKETER, Employee::RANK_SECOND);
  270. hireCrowd($advertisement, 8, Employee::PROF_MANAGER);
  271. hireCrowd($advertisement, 2, Employee::PROF_ENGINEER);
  272. hireCrowd($advertisement, 1, Employee::PROF_MARKETER, Employee::RANK_THIRD, true);
  273.  
  274. $logistics = new Department('Отдел логистики');
  275. hireCrowd($logistics, 13, Employee::PROF_MANAGER);
  276. hireCrowd($logistics, 5, Employee::PROF_MANAGER, Employee::RANK_SECOND);
  277. hireCrowd($logistics, 5, Employee::PROF_ENGINEER);
  278. hireCrowd($logistics, 1, Employee::PROF_MANAGER, Employee::RANK_FIRST, true);
  279.  
  280. $vector = new Company('Вектор');
  281. $vector->addDepartment($procurement);
  282. $vector->addDepartment($selling);
  283. $vector->addDepartment($advertisement);
  284. $vector->addDepartment($logistics);
  285.  
  286. // Начальные условия
  287. ViewHelper::printReport($vector);
  288.  
  289. // 1. Антикризисные меры: увольняю 40% инженеров во всех отделах
  290. /*function fireMassive(Department $d, $profession, $amount)
  291. {
  292.   $tolalCount = 0;
  293.   foreach ($d->employees as $employee) {
  294.   if ($employee->profession == $profession) $tolalCount += 1;
  295.   }
  296.   $toFire = intval(ceil($tolalCount * $amount));
  297.   $fired = 0;
  298.   foreach ($d->employees as $employee) {
  299.   if ($employee->profession != $profession or $employee->isBoss) continue;
  300.   if ($fired == $toFire) break;
  301.   $d->fireEmployee($employee);
  302.   $fired++;
  303.   }
  304. }
  305. foreach ($vector->getDepartments() as $department) {
  306.   fireMassive($department, Employee::PROF_ENGINEER, 0.4);
  307. }
  308. ViewHelper::printReport($vector);*/
  309.  
  310. // 2. Антикризисные меры: меняю расходы на аналитиков, делаю аналитиков начальниками
  311. // в тех департаментах, где они есть, иначе не меняю босса
  312. /*foreach ($vector->getDepartments() as $department) {
  313.   foreach ($department->employees as $employee) {
  314.   if ($employee->profession == Employee::PROF_ANALYST) {
  315.   $employee->setWageRate(1100);
  316.   $employee->setBaseCoffee(75);
  317.   $employee->setBasePages(5);
  318.   }
  319.   if ($employee->isBoss) {
  320.   $oldBoss = $employee;
  321.   break;
  322.   }
  323.   }
  324.   if ($oldBoss->profession == Employee::PROF_ANALYST) continue;
  325.   $pretendent = null;
  326.   foreach ($department->employees as $employee) {
  327.   if ($employee->profession != Employee::PROF_ANALYST) continue;
  328.   if (!$pretendent or $pretendent->rank < $employee->rank) {
  329.   $pretendent = $employee;
  330.   }
  331.   }
  332.   if ($pretendent) {
  333.   $oldBossIndex = array_search($oldBoss, $department->employees);
  334.   $department->employees[$oldBossIndex]->isBoss = false;
  335.   $pretendentIndex = array_search($pretendent, $department->employees);
  336.   $department->employees[$pretendentIndex]->isBoss = true;
  337.   }
  338. }
  339. ViewHelper::printReport($vector);*/
  340.  
  341. // 3. Антикризисные меры: повышаю на один ранг половину менеджеров 1 и 2 уровня.
  342. for ($j=0; $j < count($vector->departments); $j++) {
  343. $toUpgrade = 0;
  344. foreach ($vector->departments[$j]->employees as $e) {
  345. if ($e->rank == Employee::RANK_FIRST || Employee::RANK_SECOND) {
  346. $toUpgrade++;
  347. }
  348. }
  349. for ($i=0; $i < $toUpgrade; $i++) {
  350. if ($vector->departments[$j]->employees[$i]->rank == Employee::RANK_FIRST) {
  351. $vector->departments[$j]->employees[$i]->rank = Employee::RANK_SECOND;
  352. } elseif ($vector->departments[$j]->employees[$i]->rank == Employee::RANK_SECOND) {
  353. $vector->departments[$j]->employees[$i]->rank = Employee::RANK_THIRD;
  354. }
  355. }
  356. }
  357. ViewHelper::printReport($vector);
Success #stdin #stdout 0.02s 52432KB
stdin
Standard input is empty
stdout
Департамент                   сотр.          тугр.           кофе           стр.     тугр./стр.
-----------------------------------------------------------------------------------------------
Отдел закупок                    17         9612.5            350           3100            3.1
Отдел продаж                     24          13550            610           3325            4.1
Отдел рекламы                    36          16300            575           5450              3
Отдел логистики                  24          11375            425           3850              3
Среднее                        25.3        12709.4            490         3931.3
Всего                           101        50837.5           1960          15725
Департамент                   сотр.          тугр.           кофе           стр.     тугр./стр.
-----------------------------------------------------------------------------------------------
Отдел закупок                    17          11500            350           3100            3.7
Отдел продаж                     24          16800            610           3325            5.1
Отдел рекламы                    36          19900            575           5450            3.7
Отдел логистики                  24        14062.5            425           3850            3.7
Среднее                        25.3        15565.6            490         3931.3
Всего                           101        62262.5           1960          15725