Advertisement
nekufa

parking calculate

Jul 29th, 2015
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 6.38 KB | None | 0 0
  1. <?php
  2.  
  3. use Carbon\Carbon;
  4.  
  5. date_default_timezone_set('Europe/Moscow');
  6. require 'vendor/autoload.php';
  7.  
  8. class Parking
  9. {
  10.     protected $baseHourPrice;
  11.  
  12.     public function __construct($baseHourPrice)
  13.     {
  14.         $this->baseHourPrice = $baseHourPrice;
  15.     }
  16.  
  17.     /**
  18.      * @var Rule[]
  19.      */
  20.     private $rules = [];
  21.  
  22.     public function addRule(Rule $rule)
  23.     {
  24.         $this->rules[] = $rule;
  25.         return $this;
  26.     }
  27.  
  28.  
  29.     function calculate(Carbon $begin, Carbon $end)
  30.     {
  31.         /**
  32.          * dates list when something was changed
  33.          * @var $dates Carbon[]
  34.          */
  35.         $dates = [$begin->getTimestamp() => $begin];
  36.         $current = $begin->copy();
  37.         while ($current < $end) {
  38.             foreach ($this->rules as $rule) {
  39.                 if ($rule->shouldBeApplied($current)) {
  40.                     foreach ([$rule->getBegin($current), $rule->getEnd($current)] as $point) {
  41.                         if (!isset($dates[$point->getTimestamp()]) && $point->between($begin, $end)) {
  42.                             $dates[$point->getTimestamp()] = $point;
  43.                         }
  44.                     }
  45.                 }
  46.             }
  47.             $current = $current->copy()->addDay(1);
  48.         }
  49.  
  50.         $dates[$end->getTimestamp()] = $end;
  51.         ksort($dates);
  52.  
  53.         // calculate result
  54.         $previous = null;
  55.         $total = 0;
  56.  
  57.         foreach ($dates as $current) {
  58.             if ($previous) {
  59.  
  60.                 $hours = $current->diffInMinutes($previous) / 60;
  61.                 $sum = $this->baseHourPrice * $hours;
  62.  
  63.                 $rules = [];
  64.                 foreach ($this->rules as $rule) {
  65.                     if ($rule->shouldBeApplied($current)) {
  66.                         if ($rule->getBegin($current) < $current && $rule->getEnd($current) >= $current) {
  67.                             $sum = $rule->changeSum($sum, $hours);
  68.                             $rules[] = get_class($rule);
  69.                         }
  70.                     }
  71.                 }
  72.  
  73.                 echo $previous, ' - ', $current, PHP_EOL;
  74.                 echo json_encode(compact('hours', 'sum', 'rules')), PHP_EOL, PHP_EOL;
  75.  
  76.                 $total += $sum;
  77.             }
  78.             $previous = $current;
  79.         }
  80.         echo 'Total is: ', $total, PHP_EOL;
  81.  
  82.         return $total;
  83.     }
  84. }
  85.  
  86. interface Rule
  87. {
  88.     public function shouldBeApplied(Carbon $date);
  89.  
  90.     public function getBegin(Carbon $date);
  91.  
  92.     public function getEnd(Carbon $date);
  93.  
  94.     public function changeSum($sum);
  95. }
  96.  
  97. /**
  98.  * Pay twice when use parking during hot hours
  99.  * Class HighLoadRule
  100.  */
  101. class HighLoadRule implements Rule
  102. {
  103.     function shouldBeApplied(Carbon $date)
  104.     {
  105.         return $date->isWeekday();
  106.     }
  107.  
  108.     function getBegin(Carbon $date)
  109.     {
  110.         return $date->copy()->setTime(17, 0, 0);
  111.     }
  112.  
  113.     function getEnd(Carbon $date)
  114.     {
  115.         return $date->copy()->setTime(22, 0, 0);
  116.     }
  117.  
  118.     function changeSum($sum)
  119.     {
  120.         return $sum * 2;
  121.     }
  122. }
  123.  
  124. class WeekendRule implements Rule
  125. {
  126.  
  127.     function shouldBeApplied(Carbon $date)
  128.     {
  129.         return $date->isWeekend();
  130.     }
  131.  
  132.     function getBegin(Carbon $date)
  133.     {
  134.         return $date->copy()->setTime(0, 0, 0);
  135.     }
  136.  
  137.     function getEnd(Carbon $date)
  138.     {
  139.         return $date->copy()->setTime(24, 0, 0);
  140.     }
  141.  
  142.     function changeSum($sum)
  143.     {
  144.         return $sum / 2;
  145.     }
  146. }
  147.  
  148. class GoldHoursRule implements Rule
  149. {
  150.  
  151.     function shouldBeApplied(Carbon $date)
  152.     {
  153.         return true;
  154.     }
  155.  
  156.     function getBegin(Carbon $date)
  157.     {
  158.         return $date->copy()->setTime(18, 0, 0);
  159.     }
  160.  
  161.     function getEnd(Carbon $date)
  162.     {
  163.         return $date->copy()->setTime(19, 0, 0);
  164.     }
  165.  
  166.     function changeSum($sum)
  167.     {
  168.         return $sum * 3;
  169.     }
  170. }
  171.  
  172. class GoodMorningRule implements Rule
  173. {
  174.  
  175.     function shouldBeApplied(Carbon $date)
  176.     {
  177.         return true;
  178.     }
  179.  
  180.     function getBegin(Carbon $date)
  181.     {
  182.         return $date->copy()->setTime(9, 0, 0);
  183.     }
  184.  
  185.     function getEnd(Carbon $date)
  186.     {
  187.         return $date->copy()->setTime(10, 0, 0);
  188.     }
  189.  
  190.     function changeSum($sum)
  191.     {
  192.         return 0;
  193.     }
  194. }
  195.  
  196. $result = with(new Parking(120)) // parking with 120 RUB per hours base price
  197. ->addRule(new WeekendRule()) // on weekdays from 17 to 22 pay twice higher
  198. ->addRule(new HighLoadRule()) // on weekends pay twice lower
  199. ->addRule(new GoldHoursRule()) // any day from 18 to 19 price multiplies by 3
  200. ->addRule(new GoodMorningRule()) // any day from 9 to 10 parking is free
  201. ->calculate(
  202.     // 2015-07-24 13:30:00
  203.     Carbon::createFromTime(13, 30, 00)->setDate(2015, 7, 23),
  204.  
  205.     // 2015-07-25 17:00:00
  206.     Carbon::createFromTime(21, 00, 00)->setDate(2015, 7, 25)
  207. );
  208.  
  209. //
  210. // 2015-07-23 13:30:00 - 2015-07-23 17:00:00
  211. // {"hours":3.5,"sum":420,"rules":[]}
  212. //
  213. // 2015-07-23 17:00:00 - 2015-07-23 18:00:00
  214. // {"hours":1,"sum":240,"rules":["HighLoadRule"]}
  215. //
  216. // 2015-07-23 18:00:00 - 2015-07-23 19:00:00
  217. // {"hours":1,"sum":720,"rules":["HighLoadRule","GoldHoursRule"]}
  218. //
  219. // 2015-07-23 19:00:00 - 2015-07-23 22:00:00
  220. // {"hours":3,"sum":720,"rules":["HighLoadRule"]}
  221. //
  222. // 2015-07-23 22:00:00 - 2015-07-24 09:00:00
  223. // {"hours":11,"sum":1320,"rules":[]}
  224. //
  225. // 2015-07-24 09:00:00 - 2015-07-24 10:00:00
  226. // {"hours":1,"sum":0,"rules":["GoodMorningRule"]}
  227. //
  228. // 2015-07-24 10:00:00 - 2015-07-24 17:00:00
  229. // {"hours":7,"sum":840,"rules":[]}
  230. //
  231. // 2015-07-24 17:00:00 - 2015-07-24 18:00:00
  232. // {"hours":1,"sum":240,"rules":["HighLoadRule"]}
  233. //
  234. // 2015-07-24 18:00:00 - 2015-07-24 19:00:00
  235. // {"hours":1,"sum":720,"rules":["HighLoadRule","GoldHoursRule"]}
  236. //
  237. // 2015-07-24 19:00:00 - 2015-07-24 22:00:00
  238. // {"hours":3,"sum":720,"rules":["HighLoadRule"]}
  239. //
  240. // 2015-07-24 22:00:00 - 2015-07-25 00:00:00
  241. // {"hours":2,"sum":240,"rules":[]}
  242. //
  243. // 2015-07-25 00:00:00 - 2015-07-25 09:00:00
  244. // {"hours":9,"sum":540,"rules":["WeekendRule"]}
  245. //
  246. // 2015-07-25 09:00:00 - 2015-07-25 10:00:00
  247. // {"hours":1,"sum":0,"rules":["WeekendRule","GoodMorningRule"]}
  248. //
  249. // 2015-07-25 10:00:00 - 2015-07-25 18:00:00
  250. // {"hours":8,"sum":480,"rules":["WeekendRule"]}
  251. //
  252. // 2015-07-25 18:00:00 - 2015-07-25 19:00:00
  253. // {"hours":1,"sum":180,"rules":["WeekendRule","GoldHoursRule"]}
  254. //
  255. // 2015-07-25 19:00:00 - 2015-07-25 21:00:00
  256. // {"hours":2,"sum":120,"rules":["WeekendRule"]}
  257. //
  258. // Total is: 7500
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement