You are here

public function ReservationConflicts::bestFit in MERCI (Manage Equipment Reservations, Checkout and Inventory) 8.2

2 calls to ReservationConflicts::bestFit()
ReservationConflicts::fillBuckets in src/ReservationConflicts.php
ReservationConflicts::reservations in src/ReservationConflicts.php

File

src/ReservationConflicts.php, line 448
Contains \Drupal\merci\ReservationConflicts. Abstraction of the selection logic of an entity reference field.

Class

ReservationConflicts
A null implementation of EntityReference_SelectionHandler.

Namespace

Drupal\merci

Code

public function bestFit($dates) {
  $entity = $this->entity;
  $best_fit = array();
  $parent_conflicts = $this
    ->conflicts($dates);
  $date_value = $dates
    ->get('value')
    ->getValue();
  foreach ($entity
    ->get($this->item_field) as $delta => $item) {

    // No need to sort into buckets if there is nothing to sort into buckets.
    if (!array_key_exists($delta, $parent_conflicts) or !array_key_exists($date_value, $parent_conflicts[$delta])) {
      continue;
    }
    if ($item->entity
      ->hasField($this->quantity_field)) {
      $quantity = $item->entity
        ->get($this->quantity_field)->value;
    }
    else {
      $quantity = 1;
    }

    // Split reservations based on quantity.
    $reservations = array();
    foreach ($parent_conflicts[$delta][$date_value] as $reservation) {
      for ($i = 0; $i < $reservation->quantity; $i++) {
        $reservations[] = $reservation;
      }
    }

    // Determine how many bucket items are needed for this time period.
    // Need to sort like this:
    //            .... time ....
    // item1  x x a a a x x x x x f x e e e x x x x x
    // item2  x x x d d d d d d x x x x c c c x x x x
    // item3  x x b b b b b b b b b b b b b x x x x x
    // etc ......
    //
    //      // Order by lenght of reservation descending.
    //      // Do first-fit algorythm.
    // Sort by length of reservation.
    uasort($reservations, array(
      $this,
      "merci_bucket_cmp_length",
    ));
    $buckets = array();

    // First-fit algorythm.
    foreach ($reservations as $test_reservation) {

      // Go through each bucket item to look for a available slot for this reservation.
      //
      // Find a bucket to use for this reservation.
      for ($i = 0; $i < $quantity; $i++) {
        $fits = TRUE;

        // Bucket already has other reservations we need to check against for a fit.
        if (array_key_exists($i, $buckets)) {
          foreach ($buckets[$i] as $reservation) {
            if ($this
              ->merci_bucket_intersects($reservation, $test_reservation)) {

              //Conflict so skip saving the reservation to this slot and try to use the next bucket item.
              $fits = FALSE;
              break;
            }
          }
        }

        // We've found a slot so test the next reservation.
        if ($fits) {
          if (array_key_exists($i, $buckets)) {
            $buckets[$i] = array();
          }
          $buckets[$i][] = $test_reservation;
          break;
        }
      }
    }
    if (count($buckets)) {
      $best_fit[$delta] = $buckets;
    }
  }
  return $best_fit;
}