Example #1
0
def populate(
        settings: dict,
        queue: pd.DataFrame,
        passengers: pd.DataFrame
) -> pd.DataFrame:
    """
    Populates the initial queue with passengers according to the settings for
    the trial and returns the fully populated queue data frame.

    :param settings:
        Configuration settings for the current trial
    :param queue:
        The queue data frame for the trial
    :param passengers:
        The passengers data frame for the trial
    """

    populate_settings = get_population_settings(settings)
    populate_type = populate_settings['type']
    populate_function = None

    if populate_type == 'RANDOM':
        populate_function = randomized.populate
    elif populate_type == 'BACKWARD':
        populate_function = backward.populate
    elif populate_type == 'FORWARD':
        populate_function = forward.populate
    elif populate_type == 'CUSTOM':
        populate_function = custom.populate

    if populate_function is None:
        logging.getLogger('boarding').critical(
            'Unrecognized "populate" type in trial configs: "{}"'.format(
                settings.get('populate')
            )
        )
        sys.exit(1)

    population = populate_function(
        settings=settings,
        queue=queue,
        passengers=passengers
    )

    # Reverse the order here because population index 0 should be the first
    # passenger to board the plane and the queue is filled up from back to
    # front in the for loop below
    population.reverse()

    for queue_index, passenger_index in enumerate(population):
        queue.loc[queue_index, 'passenger'] = passenger_index

    return queue
Example #2
0
def forward(
        index_pool: list,
        settings: dict,
        queue: pd.DataFrame,
        passengers: pd.DataFrame,
        queue_index: int = None
) -> typing.Union[None, bool]:
    """
    Moves a passenger at the first queue index in the index pool. The method
    is recursive, and will trigger moves for any passengers that obstruct the
    path of the passenger if possible.

    The method returns False if the queue_index position is empty after the
    move is carried out, or True if there is a passenger in that position. The
    method returns None if there was no queue index value to process.

    :param queue_index:
        The index in the queue data frame to process. If the value is None,
        a queue index will be selected from the index pool
    :param index_pool:
        A list of all queue data frame indexes that have not yet been processed
        during the current simulation iteration.
    :param settings:
        Configuration settings for the current trial
    :param queue:
        The current queue data frame on which to operate
    :param passengers:
        The passengers data frame for the trial
    """

    queue_index = extract_queue_index(index_pool, queue_index)
    if queue_index is None:
        # All queue positions have been addressed. Stepping is complete for
        # this iteration
        return None

    queue_item = queue.iloc[queue_index]
    passenger_index = queue_item['passenger']

    if passenger_index is None:
        return False

    if passengers.loc[passenger_index, 'moved']:
        # If the passenger at this queue position has already moved during this
        # iteration, then abort the update for this position
        return True

    # No matter what outcome happens after this point, the passenger will have
    # moved, even if it's just because they are stuck waiting
    passengers.loc[passenger_index, 'moved'] = True

    if passengers.loc[passenger_index, 'delay'] > 0:
        # If the passenger is in a delay state, decrement the delay and mark
        # the passenger as having moved this iteration
        passengers.loc[passenger_index, 'delay'] -= 1
        return True

    if passengers.loc[passenger_index, 'aisle'] == queue_item['aisle']:
        # If the passenger is at their aisle, handle the seating process

        if passengers.loc[passenger_index, 'delay_interchange'] > 0:
            decrement_interchange_delay(passenger_index, passengers)
            return True

        if not passengers.loc[passenger_index, 'interchanged']:
            has_delay = assign_interchange_delay(
                settings,
                passenger_index,
                passengers
            )
            if has_delay:
                return True

        # If the seating delay and interchange delay are done, remove the
        # passenger from the queue because they are now seated
        queue.loc[queue_index, 'passenger'] = None
        queue.loc[queue_index, 'seated'] = 1 + queue_item['seated']
        passengers.loc[passenger_index, 'seated'] = True
        return False

    blocked = move_down_aisle(
        queue_index=queue_index,
        passenger_index=passenger_index,
        passengers=passengers,
        settings=settings,
        index_pool=index_pool,
        queue=queue
    )

    if blocked:
        passengers.loc[passenger_index, 'count_stuck'] += 1
    return blocked
Example #3
0
def move_down_aisle(
        queue_index: int,
        passenger_index: int,
        settings: dict,
        index_pool: list,
        passengers: pd.DataFrame,
        queue: pd.DataFrame
) -> bool:
    """
    Moves the specified passenger down the aisle if not blocked by a passenger
    located at the intended destination position.

    The method returns False if the queue_index position is empty after the
    move is carried out, or True if there is a passenger in that position.

    :param queue_index:
        The index in the queue data frame to process. If the value is None,
        a queue index will be selected from the index pool
    :param passenger_index:
        The passenger index into the passengers data frame at the current
        queue index position
    :param index_pool:
        A list of all queue data frame indexes that have not yet been processed
        during the current simulation iteration.
    :param settings:
        Configuration settings for the current trial
    :param queue:
        The current queue data frame on which to operate
    :param passengers:
        The passengers data frame for the trial
    """

    # Check to see if there is a passenger in the way at the next queue
    # position. If so, the update must abort
    dest_queue_index = queue_index + 1
    blocked = forward(
        queue_index=dest_queue_index,
        index_pool=index_pool,
        settings=settings,
        queue=queue,
        passengers=passengers
    )

    passenger = passengers.iloc[passenger_index]

    if blocked:
        # If the passenger cannot move because someone is blocking their way,
        # return True indicating that this queue position is full
        return True

    # Remove the passenger from the source position
    queue.loc[queue_index, 'passenger'] = None

    # Put the passenger at the destination location in the queue
    queue.loc[dest_queue_index, 'passenger'] = passenger_index

    dest_aisle = queue.loc[dest_queue_index, 'aisle']
    if passenger['aisle'] == dest_aisle:
        seating_delay = settings['delay']['seating']
        passengers.loc[passenger_index, 'delay'] = seating_delay

    # The passenger was moved, so there's no one in this queue position now
    return False