class Supermarket(object): """Supermarket object for simulating queuing strategies with a collection of customers.""" def __init__(self, n_checkouts, checkout_capacity, staging_capacity): self.checkouts = CheckoutManager(n_checkouts, checkout_capacity, staging_capacity) self._enqueue_strategy = self.checkouts.enqueue_random self._leftovers = 0.0 self._customer_index = 0 def _set_strategy(self, strategy): """Sets the strategy by which customers will choose which checkout queue to join.""" if strategy is "Random": self._enqueue_strategy = self.checkouts.enqueue_random elif strategy is "Shortest": self._enqueue_strategy = self.checkouts.enqueue_shortest elif strategy is "Staging": self._enqueue_strategy = self.checkouts.enqueue_staging def simulate(self, n_customers, customers_per_minute, strategy): """Runs the supermarket simulation on the given set of customers. Customers are added to the checkout queues at the given rate. The number of minutes taken to process all customers is returned.""" self._set_strategy(strategy) customers = [Customer(random.uniform(1, 5)) for _ in xrange(n_customers)] minutes = 0 while self._active_customers(customers): self._add_customers(customers, customers_per_minute) # add new customers at set rate self.checkouts.update() # update checkouts and customers for customer in customers: customer.update() minutes += 1 return minutes, customers def _active_customers(self, customers): """Checks if there is any customers left to process or currently being processed""" return self._customer_index < len(customers) or self.checkouts.has_item() def _add_customers(self, customers, customers_per_minute): """Calculates how many customers to begin queuing on the current iteration. Calculation allows for whole and floating point numbers, e.g. 2 = 2 customers per minute, 0.5 = 1 customer every 2 minutes.""" self._leftovers += customers_per_minute - int(customers_per_minute) # add decimal part to 'leftovers' registry n_customers = int(customers_per_minute) + int(self._leftovers) # add any 'whole' customers in 'leftovers' self._leftovers -= int(self._leftovers) # remove 'whole' customers from 'leftovers' for _ in xrange(n_customers): if self._customer_index < len(customers): self._enqueue_strategy(customers[self._customer_index]) self._customer_index += 1
def __init__(self, n_checkouts, checkout_capacity, staging_capacity): self.checkouts = CheckoutManager(n_checkouts, checkout_capacity, staging_capacity) self._enqueue_strategy = self.checkouts.enqueue_random self._leftovers = 0.0 self._customer_index = 0