Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* ---------------------------------------------------------------------------------
- * Class that does all the 'houskeeping'
- */
- /*
- * Requirements:
- *
- * Input:
- * 1) A list of 'date ranges' that all the timeslots must fit in one of the ranges
- * 2) A list of 'required' dates - these are fixed and will always be in the final list
- * 3) A list of 'candidate' dates
- *
- * Output:
- * 1) A 'final list of 'none-overlapping' dates
- *
- * Where:
- * a) The first 'required' data is a 'start' date
- * i.e. All candidate dates must be on or after this date.
- *
- * b) No date ranges must overlap.
- */
- class TimeSlotList
- {
- /**
- * A list of all the dates that:
- * 1) After the 'required' start date
- * 2) Do not overlap with any 'required' date
- *
- * @var array $candidates
- */
- private $candidates = array();
- /**
- * Any date record we didn't use.
- *
- * @var array $unused
- */
- private $unused = array();
- /**
- * List of dates that must be included in the 'final' list.
- * The earliest date is assumed to be a start date and everything must be later.
- *
- * @var array $required
- */
- private $required = array();
- /**
- * List of dates ranges that candidate dates must be between
- *
- * @var array $ranges
- */
- private $ranges = array();
- /**
- * Ordered list of `none overlapping' dates from the Required and candidates
- *
- * @var array $final
- */
- private $final = array();
- /**
- * Current List of paths with associated score
- *
- * The top one is the current best one
- */
- private $currentPath = array();
- /**
- * These are the date lists.
- * They will be converted, sorted and filters as required.
- *
- * @param array $requiredDates
- * @param array $candidateDates
- * @return void
- */
- public function __construct(array $requiredDates = array(),
- array $candidateDates = array(),
- array $ranges = array())
- {
- if (!empty($ranges)) {
- $this->setRanges($ranges);
- }
- if (!empty($requiredDates)) {
- $this->setRequired($requiredDates);
- }
- if (!empty($candidateDates)) {
- $this->setCandidates($candidateDates);
- }
- }
- /**
- * Process each range in turn and add the timeslotes to the the final list
- *
- * Known conditions:
- * o Both lists are in start date order
- * o No candidates overlap with any Required date
- * o The candidates may overlap with each other - Hmm... need to check...
- *
- *
- * @return array
- */
- public function generateList()
- {
- $bestList = array();
- foreach ($this->ranges as $range) {
- $availableList = $this->getAllDatesWithinRange($range);
- $curRange = new TimeSlotRange($range,
- $availableList['required'],
- $availableList['candidates']);
- $whenList = $curRange->generateList();
- $bestList = array_merge($bestList, $whenList);
- }
- $this->final = $bestList;
- return $bestList;
- }
- /**
- * Convert ranges to date range and sort them
- *
- * @param array $requiredDates
- */
- public function setRanges(array $dates)
- {
- $this->ranges = $dates;
- }
- /**
- * Convert Required dates to date range and sort them
- *
- * @param array $requiredDates
- */
- public function setRequired(array $dates)
- {
- foreach ($dates as $when) {
- $when->setIsRequired();
- $this->required[] = $when;
- }
- }
- /**
- * setter for candidates - will convert to date range
- *
- * @param array $candidateDates
- *
- * @return void;
- */
- public function setCandidates(array $dates)
- {
- foreach ($dates as $when) {
- if ($when->isRequired()) {
- $this->required[] = $when;
- } else {
- $this->candidates[] = $when;
- }
- }
- }
- /**
- * Extract all timeslots within the range as two arrays
- *
- * @param ITimeslot $range
- *
- * @return array Containing an array ('required') and array('candidates') of all the timeslots
- *
- */
- public function getAllDatesWithinRange(ITimeSlot $range)
- {
- $whenList = array('required' => array(), 'candidates' => array());
- foreach ($this->required as $when) {
- if ($range->isInside($when)) {
- $whenList['required'][] = $when;
- }
- }
- foreach ($this->candidates as $when) {
- if ($range->isInside($when)) {
- if (! TimeSlotRange::isOverlapAny($when, $whenList['required'])) {
- $whenList['candidates'][] = $when;
- }
- }
- }
- return $whenList;
- }
- public function displayWhenList(array $whenList, $title = 'whenList', $sort = true)
- {
- if ($sort) {
- usort($whenList,
- function ($when1, $when2) {
- return $when1['startTime'] - $when2['startTime'];
- });
- }
- echo PHP_EOL, PHP_EOL, $title;
- foreach ($whenList as $when) {
- $this->displayWhen($when);
- }
- echo '<pre>';
- }
- /**
- * Show a date formatted for debugging purposes
- *
- * @param array $when
- * @return void
- */
- public function displayWhen(ITimeSlot $when)
- {
- echo PHP_EOL, 'date: ', $when->getStartDate()->format('Y-m-d H:i:s'),
- ' len: ', sprintf('%4d', $when['duration']),
- ' end: ', $when->getEndDate()->format('Y-m-d H:i:s'),
- ' start: ', $when['startTime'],
- ' end: ', $when['endTime'],
- ' Required? ', ($when['isRequired'] ? 'true' : 'false'),
- (!empty($when['fail'])
- ? ' fail: ' . $when['fail'] : '');
- }
- public function sortEndTime(&$timeSlots)
- {
- // sort by end times - makes it easy to reason about
- usort($timeSlots,
- function ($when1, $when2) {
- $order = $when1['endTime'] - $when2['endTime'];
- if ($order === 0) { // want the largest first
- return $when2['duration'] - $when1['duration'];
- }
- return $order;
- });
- return;
- }
- public function sortStartTime(&$timeSlots)
- {
- // sort by end times - makes it easy to reason about
- usort($timeSlots,
- function ($when1, $when2) {
- $order = $when1['startTime'] - $when2['startTime'];
- if ($order === 0) { // want the largest first
- return $when2['duration'] - $when1['duration'];
- }
- return $order;
- });
- return;
- }
- /*
- * `Getters` so you can see what happened
- */
- public function getRequired() { return $this->required; }
- public function getRanges() { return $this->ranges; }
- public function getUnused() { return $this->unused; }
- public function getCandidates() { return $this->candidates; }
- public function getFinal() { return $this->final; }
- /**
- * properties - for those of us that like them
- */
- public function __get($name)
- {
- if (property_exists($this, $name)) {
- return $this->$name;
- }
- return null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement