Beispiel #1
0
    def get_best_adjacent_in_section(self, section_id, seat_count, expiry_seconds=constants.DEFAULT_PREALLOCATION_EXPIRY):
        """
            Tries to get the best available seats available in the section
        """
        # Try to get the section by id
        try:
            section = (section for section in self.layout_data if section["section_id"] == section_id).__next__()
        except StopIteration as e:
            raise exp.NoSuchSectionException
           
        # Iterate through the rows in the section starting with the "highest quality" rows
        row_quality_list = sorted(section["rows"], key = lambda row: row["quality"])
        
        for row in row_quality_list:
            # Try to find a row that has enough seats
            available_seats = [seat for seat in row['seats'] if seat["status"] == constants.SEAT_FREE]
            
            # TODO improvement would be to find the number of consecutive seats that fit the requirement most accurately
            # i.e. If there is multiple consecutive seats numbers available that fit the requirement, use the smallest
            max_consecutive_seats = (util.max_consecutive_series([seat["seat_id"] for seat in available_seats]))

            # Check the correct amount of consecutive seats are available
            if len(available_seats) >= seat_count and seat_count <= len(max_consecutive_seats):
                seat_ids_allocated = []
                
                # Get those available seats with IDs that match the consecutive seat numbers
                selected_seats = [seat for seat in available_seats if seat["seat_id"] in max_consecutive_seats]
                
                # Limit the amount of seats to the amount we actually want from the selected seats list
                for seat in selected_seats[:seat_count]:
                    seat["status"] = constants.SEAT_PREBOOKED
                    
                    seat_ids_allocated.append(seat["seat_id"])
                
                    # decrement available seats counter
                    self.available_seats -= 1
                
                # Make a note of the prebookings with an expiry time to allow future expiring
                # if the booking is not complete
                prebooking_token = str(uuid.uuid4())
                expiry_time = datetime.datetime.now() + datetime.timedelta(0, expiry_seconds)
                self.preallocated[prebooking_token] = {'section_id' : section_id,
                                                       'row_id' : row["row_id"],
                                                       'seat_ids' : seat_ids_allocated,
                                                       'expiry_time' : expiry_time
                }
                
                # Include the row and seat ids in the return message
                return_value = {'status' : True, 'errors' : [], 'data' : {'prebook_token' : prebooking_token,
                                                                          'expiry_time' : expiry_time,
                                                                          'row_id' : row["row_id"],
                                                                          'row_quality' : row['quality'],
                                                                          'seat_ids' : seat_ids_allocated,
                                                                         }
                }
                
                break
        else:
            # No row in this section had enough seats available to satisfy the amount requested
            return_value = {'status' : False, 'errors' : [err.SEAT_REQUIREMENT_COULD_NOT_BE_FILLED], 'data' : {}}
        
        return return_value
Beispiel #2
0
 def test_consecutive_seat_finder(self):
     self.assertEqual(util.max_consecutive_series([1,2,3,5,6,9]), [1,2,3])
     self.assertEqual(util.max_consecutive_series([1,3,5]), [1,])
     self.assertEqual(util.max_consecutive_series([1,2,3,5,6,9, 14,15,16,17]), [14,15,16,17])
Beispiel #3
0
    def get_best_adjacent_in_event(self, seat_count, expiry_seconds=constants.DEFAULT_PREALLOCATION_EXPIRY):
        """
            Tries to get the best available seats in the venue by checking all sections
        """
        best_found = collections.defaultdict(list) # Defaultdict of best seat combos found by row quality
        
        # Get all sections
        for section in self.layout_data:
            # Iterate through the rows in the section starting with the "highest quality" rows
            row_quality_list = sorted(section["rows"], key = lambda row: row["quality"])
            
            for row in row_quality_list:
                # Try to find a row that has enough seats
                available_seats = [seat for seat in row['seats'] if seat["status"] == constants.SEAT_FREE]

                # TODO improvement would be to find the number of consecutive seats that fit the requirement most accurately
                # i.e. If there is multiple consecutive seats numbers available that fit the requirement, use the smallest
                max_consecutive_seats = (util.max_consecutive_series([seat["seat_id"] for seat in available_seats]))
                
                # Check the correct amount of consecutive seats are available
                if len(available_seats) >= seat_count and seat_count <= len(max_consecutive_seats):
                    # Get those available seats with IDs that match the consecutive seat numbers
                    selected_seats = [seat for seat in available_seats if seat["seat_id"] in max_consecutive_seats][:seat_count]
                    
                    possible_seat_selection = {'section_id' : section['section_id'],
                                               'row_id' : row["row_id"],
                                               'row_quality' : row["quality"],
                                               'seat_ids' : [seat["seat_id"] for seat in selected_seats],
                    }
                    
                    # Add to defualt dict grouped by row quality
                    best_found[row["quality"]].append(possible_seat_selection)
        
        # Use the first "best" row we find
        for best in sorted(best_found.items())[:1]:
            # Use the first one we get to
            best_booking = (best[1][0])
            
            # Get section, row and seat objects
            section, row, seats = self.get_section_row_and_seats_from_ids(best_booking["section_id"], best_booking["row_id"], best_booking["seat_ids"])
            
            # Preallocate the seats
            for seat in seats:
                seat["status"] = constants.SEAT_PREBOOKED
                self.available_seats -= 1 # decrement available seats counter
            
            # Make a note of the prebookings with an expiry time to allow future expiring
            # if the booking is not complete
            prebooking_token = str(uuid.uuid4())
            expiry_time = datetime.datetime.now() + datetime.timedelta(0, expiry_seconds)
            self.preallocated[prebooking_token] = {'section_id' : best_booking["section_id"],
                                                   'row_id' : best_booking["row_id"],
                                                   'seat_ids' : best_booking["seat_ids"],
                                                   'expiry_time' : expiry_time
            }

            # Include the section, row and seat ids in the return message
            return_value = {'status' : True, 'errors' : [], 'data' : {'prebook_token' : prebooking_token,
                                                                       'expiry_time' : expiry_time,
                                                                       'section_id' : best_booking["section_id"],
                                                                       'row_id' : best_booking["row_id"],
                                                                       'seat_ids' : best_booking["seat_ids"],
                                                                      }
            }
            break
            
        else:
            # No seats could be found in the entire Event
            return_value = {'status' : False, 'errors' : [err.SEAT_REQUIREMENT_COULD_NOT_BE_FILLED], 'data' : {}}
        
        return return_value