

import numpy as np

def expected_remaining_time(mean_time=10.):
    return np.random.exponential(mean_time)

def next_arrival(arrival_i,mean_time=7.):
    return arrival_i + np.random.exponential(mean_time)

maximum_time = 500


def service_simulation(maximum_time, initial_time=0):
    arrivals_on_service = []
    arrivals_to_departures = {}

    arrival_i = next_arrival(initial_time)
    t_j = arrival_i

    expected_remaining_i = expected_remaining_time()
    expected_departure_i = t_j + expected_remaining_i
    next_expected_departure = expected_departure_i
    next_expected_arrival = arrival_i
    arrivals_on_service.append(next_expected_arrival)
    while t_j < maximum_time:
        arrival_i = next_arrival(arrival_i)
        arrivals_on_service.append(arrival_i)
        while next_expected_departure < arrival_i:
            #============================
            #somebody left the service
            #============================
            succesful_departure = next_expected_departure
            t_j = succesful_departure
            arrivals_to_departures[next_expected_arrival] = succesful_departure
            arrivals_on_service.remove(next_expected_arrival)
            #=================================
            # redo all service information
            #=================================
            expected_departures = []
            for arrival_on_service_k in arrivals_on_service:
                expected_remaining_k = expected_remaining_time()
                if arrival_on_service_k < t_j:
                    expected_departure_k = t_j + expected_remaining_k
                else:
                    expected_departure_k = arrival_on_service_k + expected_remaining_k
                expected_departures.append((expected_departure_k,arrival_on_service_k))
            expected_departures.sort()
            if len(expected_departures) > 0:
                next_expected_departure,next_expected_arrival = expected_departures.pop(0)
            else:
                next_expected_departure = np.inf
        #==================================
        # redo all service information
        #==================================
        t_j = arrival_i
        expected_departures = []
        for arrival_on_service_k in arrivals_on_service:
            expected_remaining_k = expected_remaining_time()
            expected_departure_k = t_j + expected_remaining_k
            expected_departures.append((expected_departure_k,arrival_on_service_k))
        expected_departures.sort()
        if len(expected_departures) > 0:
            next_expected_departure, next_expected_arrival = expected_departures.pop(0)
        else:
            next_expected_departure = np.inf
    for unfinished_arrivals in arrivals_on_service:
        arrivals_to_departures[unfinished_arrivals] = np.inf

    return arrivals_to_departures

if __name__=="__main__":
    arrivals_to_departures = service_simulation(maximum_time, initial_time=0)
    print arrivals_to_departures