123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- <?php
- namespace App\Helpers;
- use DateTime;
- class TimeLine {
- public $start = null;
- public $end = null;
- public $available = [];
- public $unavailable = [];
- public $removeStart = null;
- public $removeEnd = null;
- public function __construct(DateTime $_start, DateTime $_end)
- {
- $this->start = $_start->getTimestamp();
- $this->end = $_end->getTimestamp();
- }
- public function addAvailability(DateTime $_start, DateTime $_end) {
- $this->available[] = new TimeSlot($_start, $_end);
- // sort by start
- usort($this->available, function ($item1, $item2) {
- return $item1->start <=> $item2->start;
- });
- // compact (join adjacent overlapping slots)
- // $this->vdump($this->available);
- $this->normalize();
- $this->vdump($this->available);
- }
- public function removeAvailability(DateTime $_start, DateTime $_end) {
- $this->removeStart = $_start->getTimestamp();
- $this->removeEnd = $_end->getTimestamp();
- $this->cleanRemove();
- $removeStart = null;
- $removeSnd = null;
- // sort by start
- usort($this->available, function ($item1, $item2) {
- return $item1->start <=> $item2->start;
- });
- $this->normalize();
- $this->vdump($this->available);
- }
- private function cleanRemove() {
- $allDone = true;
- for ($i=0; $i<count($this->available); $i++) {
- // removeStart at or after slot start
- // removeEnd at or before slot end
- // split slot into 2
- if($this->removeStart >= $this->available[$i]->start &&
- $this->removeEnd <= $this->available[$i]->end) {
- $newSlot = new TimeSlot(new DateTime(), new DateTime());
- $newSlot->start = $this->removeEnd;
- $newSlot->end = $this->available[$i]->end;
- $this->available[$i]->end = $this->removeStart;
- array_splice($this->available, $i+1, 0, [$newSlot]);
- $allDone = true;
- break;
- }
- // removeStart at or after slot start
- // removeStart at or before slot end
- // update slot to end at removeStart
- if($this->removeStart >= $this->available[$i]->start &&
- $this->removeStart <= $this->available[$i]->end) {
- $this->available[$i]->end = $this->removeStart;
- $allDone = false;
- break;
- }
- // process removeEnd
- // removeEnd at or after slot start
- // removeEnd at or before slot end
- // update slot to start at removeEnd
- if($this->removeEnd >= $this->available[$i]->start &&
- $this->removeEnd <= $this->available[$i]->end) {
- $this->available[$i]->start = $this->removeEnd;
- $allDone = false;
- break;
- }
- }
- if(!$allDone) {
- $this->normalize(); // recurse till clean
- }
- }
- private function normalize() {
- $allDone = true;
- for ($i=0; $i<count($this->available)-1; $i++) {
- if($this->available[$i]->end >= $this->available[$i+1]->start && // ends in the middle of next slot
- $this->available[$i]->end <= $this->available[$i+1]->end)
- {
- // extend self & delete next
- $this->available[$i]->end = $this->available[$i+1]->end;
- array_splice($this->available, $i+1, 1);
- $allDone = false;
- break;
- }
- if($this->available[$i]->end >= $this->available[$i+1]->end) // ends after next slot end
- {
- // delete next
- array_splice($this->available, $i+1, 1);
- $allDone = false;
- break;
- }
- if($this->available[$i]->start >= $this->available[$i]->end) // starts and ends at the same time!
- {
- // delete self
- array_splice($this->available, $i, 1);
- $allDone = false;
- break;
- }
- }
- if(!$allDone) {
- $this->normalize(); // recurse till clean
- }
- }
- public function vdump($_x) {
- // echo "<pre>";
- // print_r($_x);
- // echo "</pre><hr>";
- }
- }
|