diff --git a/src/Ramcar/HubCriteria.php b/src/Ramcar/HubCriteria.php index cb42ce04..001b4cd3 100644 --- a/src/Ramcar/HubCriteria.php +++ b/src/Ramcar/HubCriteria.php @@ -8,13 +8,13 @@ use DateTime; class HubCriteria { - protected $point; // coordinates of source - protected $limit_results; // number of results to return - protected $limit_distance; // distance limit for search in km - protected $has_inventory; // flag if we need to check for inventory - protected $jo_type; // jo service needed - protected $date_time; // date and time to check if hub is open or not - protected $items; // array of items: items[id] = quantity to check for and has_inventory is true + protected $point; // coordinates of source + protected $limit_results; // number of results to return + protected $limit_distance; // distance limit for search in km + protected $flag_inventory_check; // flag if we need to check for inventory + protected $jo_type; // jo service needed + protected $date_time; // date and time to check if hub is open or not + protected $items; // array of items: items[id] = quantity to check for and has_inventory is true public function __construct() { @@ -55,15 +55,15 @@ class HubCriteria return $this->limit_distance; } - public function setHasInventory($has_inventory = true) + public function setInventoryCheck($flag_inventory_check = true) { - $this->has_inventory = $has_inventory; + $this->flag_inventory_check = $flag_inventory_check; return $this; } - public function hasInventory() + public function hasInventoryCheck() { - return $this->has_inventory; + return $this->flag_inventory_check; } public function setJoType($jo_type) diff --git a/src/Service/HubSelector.php b/src/Service/HubSelector.php index 3ab1eb90..ad6f54dd 100644 --- a/src/Service/HubSelector.php +++ b/src/Service/HubSelector.php @@ -8,6 +8,7 @@ use CrEOF\Spatial\PHP\Types\Geometry\Point; use App\Entity\Hub; +use App\Service\RedisClientProvider; use App\Service\InventoryManager; use App\Ramcar\HubCriteria; @@ -16,11 +17,15 @@ use App\Ramcar\ServiceType; class HubSelector { protected $em; + protected $im; + protected $redis; - public function __construct(EntityManagerInterface $em, InventoryManager $im) + public function __construct(EntityManagerInterface $em, InventoryManager $im, + RedisClientProvider $redis) { $this->em = $em; $this->im = $im; + $this->redis = $redis; } public function find(HubCriteria $criteria) @@ -29,125 +34,100 @@ class HubSelector $limit_results = $criteria->getLimitResults(); $limit_distance = $criteria->getLimitDistance(); $jo_type = $criteria->getJoType(); - $has_inventory = $criteria->hasInventory(); + $flag_inventory_check = $criteria->hasInventoryCheck(); $items = $criteria->getItems(); $date_time = $criteria->getDateTime(); $results = []; - // check for jo type - if (($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) || - ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) + // get all the hubs within distance + $filtered_hubs = $this->getClosestHubs($point, $limit_distance); + + // filter the first hub results for date and opening times + $hubs_date_time = $this->filterHubsByDateAndTime($filtered_hubs, $date_time); + $filtered_hubs = $hubs_date_time; + + // filter jo types + $hubs_jo_type = $this->filterHubsByJoType($filtered_hubs, $jo_type); + $filtered_hubs = $hubs_jo_type; + + // inventory filter + $hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $has_inventory, + $jo_type, $items); + $filtered_hubs = $hubs_inventory; + + // round robin filter + $hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs); + $filtered_hubs = $hubs_round_robin; + + // max results filter + $hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results); + $filtered_hubs = $hubs_max_result; + + $results = $filtered_hubs; + + return $results; + } + + protected function filterHubsByRoundRobin($hubs) + { + } + + protected function filterHubsByMaxResults($hubs, $limit_result) + { + } + + protected function filterHubsByJoType($hubs, $jo_type) + { + } + + protected function filterHubsByDateAndTime($hubs, $date_time) + { + if (empty($hubs)) + return $hubs; + + if ($date_time == null) + return $hubs; + + $results = []; + + foreach ($hubs as $hub) { - // check if we need to get inventory - if ($has_inventory) - { - if ($date_time != null) - { - // call function for jo type, inventory == true, and check for date and time - $results = $this->getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time); - } - else - { - // call function for jo type and inventory == true - $results = $this->getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items); - } - } - else - { - if ($date_time != null) - { - // call function for jo type and check for date and time - $results = $this->getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time); - } - else - { - // call function for jo type only - $results = $this->getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type); - } - } + // go through each hub's opening times to check if hub is open + // for the specified time } - else + + return $results; + } + + protected function filterHubsByInventory($hubs, $has_inventory, $jo_type, $items) + { + if (empty($hubs)) + return $hubs; + + if (!$flag_inventory_check) + return $hubs; + + $results = []; + if ($flag_inventory_check) { - // no need to check for items and inventory. - // check for date and time - if ($date_time != null) + foreach ($hubs as $hub) { - // call function that gets hubs with opening times - $results = $this->getClosestHubsWithTime($point, $limit_results, $limit_distance, $date_time); - } - else - { - // call default function that just gets the hubs within distance limit - // and number of results - $results = $this->getClosestHubs($point, $limit_results, $limit_distance); + if ($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW) + { + // call inventory + } + if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY) + { + // call inventory + } } } return $results; } - protected function getClosestHubsWithJoTypeAndInventoryAndTime($point, $limit_results, $limit_distance, $jo_type, $items, $date_time) - { - // get closest hubs that are open at the given time offering jo_type service based on st_distance function from db - $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: add the jo_type/service parameter - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_data = []; - foreach ($result as $row) - { - $hubs[] = $row[0]; - - // get coordinates of hub - $hub_coordinates = $row[0]->getCoordinates(); - - $cust_lat = $point->getLatitude(); - $cust_lng = $point->getLongitude(); - - $hub_lat = $hub_coordinates->getLatitude(); - $hub_lng = $hub_coordinates->getLongitude(); - - // get distance in kilometers from customer point to hub point - $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); - - if ($dist < $limit_distance) - { - // TODO: insert call to function that will check inventory here - // checkInventory is going to return true if hub has all items - $this->checkInventory($items, $$row[0]); - // TODO: add checking here if hub has all items or not - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithJoTypeAndInventory($point, $limit_results, $limit_distance, $jo_type, $items) + protected function getClosestHubs(Point $point, $limit_distance) { // get closest hubs based on st_distance function from db $query_string = 'SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h WHERE h.status_open = true ORDER BY dist'; @@ -156,15 +136,11 @@ class HubSelector ->setParameter('lat', $point->getLatitude()) ->setParameter('lng', $point->getLongitude()); - // TODO: add the jo_type/service parameter - - $query->setMaxResults($limit_results); - // error_log($query->getSql()); $result = $query->getResult(); $hubs = []; - $final_data = []; + $hubs_data = []; foreach ($result as $row) { $hubs[] = $row[0]; @@ -183,11 +159,7 @@ class HubSelector if ($dist < $limit_distance) { - // TODO: insert call to function that will check inventory here - // checkInventory is going to return true if hub has all items - $this->checkInventory($items, $$row[0]); - // TODO: add checking here if hub has all items or not - $final_data[] = [ + $hubs_data[] = [ 'hub' => $row[0], 'db_distance' => $row['dist'], 'distance' => $dist, @@ -196,211 +168,7 @@ class HubSelector } } - return $final_data; - } - - protected function getClosestHubsWithJoTypeAndTime($point, $limit_results, $limit_distance, $jo_type, $date_time) - { - // get closest hubs that are open at the given time offering jo_type service based on st_distance function from db - $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: add the jo_type/service parameter - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_data = []; - foreach ($result as $row) - { - $hubs[] = $row[0]; - - // get coordinates of hub - $hub_coordinates = $row[0]->getCoordinates(); - - $cust_lat = $point->getLatitude(); - $cust_lng = $point->getLongitude(); - - $hub_lat = $hub_coordinates->getLatitude(); - $hub_lng = $hub_coordinates->getLongitude(); - - // get distance in kilometers from customer point to hub point - $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); - - if ($dist < $limit_distance) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithJoType($point, $limit_results, $limit_distance, $jo_type) - { - // get closest hubs offering jo_type service based on st_distance function from db - $query_string = 'SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h WHERE h.status_open = true ORDER BY dist'; - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: add the jo type/service parameter here - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_data = []; - foreach ($result as $row) - { - $hubs[] = $row[0]; - - // get coordinates of hub - $hub_coordinates = $row[0]->getCoordinates(); - - $cust_lat = $point->getLatitude(); - $cust_lng = $point->getLongitude(); - - $hub_lat = $hub_coordinates->getLatitude(); - $hub_lng = $hub_coordinates->getLongitude(); - - // get distance in kilometers from customer point to hub point - $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); - - if ($dist < $limit_distance) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubsWithTime(Point $point, $limit_results, $limit_distance, $date_time) - { - // get closest hubs that are open at the given time based on st_distance function from db - $query = $this->em->createQuery('SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h' . ($time ? ' WHERE :time BETWEEN h.time_open AND h.time_close' : '') . ' ORDER BY dist'); - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - // TODO: have to add date and time to query - // right now, hub only has opening times - // so we extract the time from date_time - $time = $date_time->format("H:i:s"); - if ($time) { - $query->setParameter('time', $time); - } - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_data = []; - foreach ($result as $row) - { - $hubs[] = $row[0]; - - // get coordinates of hub - $hub_coordinates = $row[0]->getCoordinates(); - - $cust_lat = $point->getLatitude(); - $cust_lng = $point->getLongitude(); - - $hub_lat = $hub_coordinates->getLatitude(); - $hub_lng = $hub_coordinates->getLongitude(); - - // get distance in kilometers from customer point to hub point - $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); - - if ($dist < $limit_distance) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; - } - - protected function getClosestHubs(Point $point, $limit_results, $limit_distance) - { - // get closest hubs based on st_distance function from db - $query_string = 'SELECT h, st_distance(h.coordinates, point(:lng, :lat)) as dist FROM App\Entity\Hub h WHERE h.status_open = true ORDER BY dist'; - - $query = $this->em->createQuery($query_string) - ->setParameter('lat', $point->getLatitude()) - ->setParameter('lng', $point->getLongitude()); - - $query->setMaxResults($limit_results); - - // error_log($query->getSql()); - $result = $query->getResult(); - - $hubs = []; - $final_data = []; - foreach ($result as $row) - { - $hubs[] = $row[0]; - - // get coordinates of hub - $hub_coordinates = $row[0]->getCoordinates(); - - $cust_lat = $point->getLatitude(); - $cust_lng = $point->getLongitude(); - - $hub_lat = $hub_coordinates->getLatitude(); - $hub_lng = $hub_coordinates->getLongitude(); - - // get distance in kilometers from customer point to hub point - $dist = $this->distance($cust_lat, $cust_lng, $hub_lat, $hub_lng); - - if ($dist < $limit_distance) - { - $final_data[] = [ - 'hub' => $row[0], - 'db_distance' => $row['dist'], - 'distance' => $dist, - 'duration' => 0, - ]; - } - } - - return $final_data; + return $hubs_data; } protected function checkInventory($items, $hub)