Ejemplo n.º 1
0
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(
         host=mongodb_host, port=mongodb_port)
     self.edge_documents = []
     self.traffic_event_documents = []
     self.minimum_latitude = float('inf')
     self.maximum_latitude = float('-inf')
     self.minimum_longitude = float('inf')
     self.maximum_longitude = float('-inf')
     log(module_name='traffic_data_parser',
         log_type='DEBUG',
         log_message='mongodb_database_connection: established')
 def __init__(self):
     log(module_name='mongodb_database_connection_test',
         log_type='INFO',
         log_message='initialize_mongodb_database_connection: starting')
     self.start_time = time.time()
     self.mongodb_database_connection = MongodbDatabaseConnection(
         host=mongodb_host, port=mongodb_port)
     self.elapsed_time = time.time() - self.start_time
     log(module_name='mongodb_database_connection_test',
         log_type='INFO',
         log_message=
         'initialize_mongodb_database_connection: finished - elapsed_time = '
         + str(self.elapsed_time) + ' sec')
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     log(
         module_name="travel_requests_simulator",
         log_type="DEBUG",
         log_message="mongodb_database_connection: established",
     )
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     self.edge_documents = []
     self.traffic_event_documents = []
     self.minimum_longitude = float("inf")
     self.maximum_longitude = float("-inf")
     self.minimum_latitude = float("inf")
     self.maximum_latitude = float("-inf")
     log(module_name="traffic_data_parser", log_type="DEBUG", log_message="mongodb_database_connection: established")
Ejemplo n.º 5
0
 def __init__(self):
     log(module_name='mongodb_database_connection_test', log_type='INFO',
         log_message='initialize_mongodb_database_connection: starting')
     self.start_time = time.time()
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     self.elapsed_time = time.time() - self.start_time
     log(module_name='mongodb_database_connection_test', log_type='INFO',
         log_message='initialize_mongodb_database_connection: finished - elapsed_time = ' +
                     str(self.elapsed_time) + ' sec')
Ejemplo n.º 6
0
 def __init__(self, osm_filename):
     """
     :param osm_filename: Directory of the input OSM file.
     :type osm_filename: string
     """
     self.osm_filename = osm_filename
     self.address_documents_dictionary = {}
     self.bus_stop_documents_dictionary = {}
     self.edge_documents_dictionary = {}
     self.node_documents_dictionary = {}
     self.point_documents_dictionary = {}
     self.way_documents_dictionary = {}
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     log(module_name='osm_parser', log_type='DEBUG',
         log_message='mongodb_database_connection: established')
class TravelRequestsSimulator(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(
            host=mongodb_host, port=mongodb_port)
        log(module_name='travel_requests_simulator',
            log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def clear_travel_requests_collection(self):
        """
        Clear all the documents of the TravelRequests collection.

        :return: None
        """
        self.mongodb_database_connection.clear_travel_request_documents_collection(
        )
        log(module_name='travel_requests_simulator',
            log_type='DEBUG',
            log_message='clear_travel_request_documents_collection: ok')

    def delete_travel_request_documents(self,
                                        object_ids=None,
                                        client_ids=None,
                                        bus_line_ids=None,
                                        min_departure_datetime=None,
                                        max_departure_datetime=None):
        """
        Delete multiple travel_request_documents.

        :param object_ids: [ObjectId]
        :param client_ids: [int]
        :param bus_line_ids: [int]
        :param min_departure_datetime: datetime
        :param max_departure_datetime
        :return: None
        """
        self.mongodb_database_connection.delete_travel_request_documents(
            object_ids=object_ids,
            client_ids=client_ids,
            bus_line_ids=bus_line_ids,
            min_departure_datetime=min_departure_datetime,
            max_departure_datetime=max_departure_datetime)
        log(module_name='travel_requests_simulator',
            log_type='DEBUG',
            log_message='delete_travel_request_documents: ok')

    def generate_random_travel_request_documents(
            self, initial_datetime, min_number_of_travel_request_documents,
            max_number_of_travel_request_documents):
        """
        Generate random number of travel_request_documents for each bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        :param initial_datetime: datetime
        :param min_number_of_travel_request_documents: int
        :param max_number_of_travel_request_documents: int
        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            number_of_travel_request_documents = random.randint(
                min_number_of_travel_request_documents,
                max_number_of_travel_request_documents)
            self.generate_travel_request_documents(
                initial_datetime=initial_datetime,
                number_of_travel_request_documents=
                number_of_travel_request_documents,
                bus_line=bus_line)

    def generate_travel_request_documents(self,
                                          initial_datetime,
                                          number_of_travel_request_documents,
                                          bus_line=None,
                                          bus_line_id=None):
        """
        Generate a specific number of travel_request_documents, for the selected bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        :param initial_datetime: datetime
        :param number_of_travel_request_documents: int
        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """
        # 1: The inputs: initial_datetime, number_of_travel_request_documents, and (bus_line or bus_line_id)
        #    are provided to the Travel Requests Simulator, so as a specific number of travel_request_documents
        #    to be generated, for the selected bus_line, for a 24hour period starting from
        #    the selected datetime.
        #
        # 2: If the provided bus_line is None, then the Travel Requests Simulator retrieves from the System Database
        #    the bus_line which corresponds to the provided bus_line_id.
        #
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(
                bus_line_id=bus_line_id)
        else:
            pass

        bus_stops = bus_line.get('bus_stops')
        number_of_bus_stops = len(bus_stops)

        # 3: The Travel Requests Simulator generates the travel_request_documents, taking into consideration
        #    the variation of transportation demand during the hours of the day.
        #
        # distribution_weighted_datetimes = [
        #     (initial_datetime + timedelta(hours=0), 1),
        #     (initial_datetime + timedelta(hours=1), 1),
        #     (initial_datetime + timedelta(hours=2), 1),
        #     (initial_datetime + timedelta(hours=3), 1),
        #     (initial_datetime + timedelta(hours=4), 1),
        #     (initial_datetime + timedelta(hours=5), 1),
        #     (initial_datetime + timedelta(hours=6), 1),
        #     (initial_datetime + timedelta(hours=7), 1),
        #     (initial_datetime + timedelta(hours=8), 1),
        #     (initial_datetime + timedelta(hours=9), 1),
        #     (initial_datetime + timedelta(hours=10), 1),
        #     (initial_datetime + timedelta(hours=11), 1),
        #     (initial_datetime + timedelta(hours=12), 1),
        #     (initial_datetime + timedelta(hours=13), 1),
        #     (initial_datetime + timedelta(hours=14), 1),
        #     (initial_datetime + timedelta(hours=15), 1),
        #     (initial_datetime + timedelta(hours=16), 1),
        #     (initial_datetime + timedelta(hours=17), 1),
        #     (initial_datetime + timedelta(hours=18), 1),
        #     (initial_datetime + timedelta(hours=19), 1),
        #     (initial_datetime + timedelta(hours=20), 1),
        #     (initial_datetime + timedelta(hours=21), 1),
        #     (initial_datetime + timedelta(hours=22), 1),
        #     (initial_datetime + timedelta(hours=23), 1)
        # ]
        distribution_weighted_datetimes = [
            (initial_datetime + timedelta(hours=i),
             travel_requests_simulator_datetime_distribution_weights[i])
            for i in range(0, 24)
        ]
        datetime_population = [
            val for val, cnt in distribution_weighted_datetimes
            for i in range(cnt)
        ]
        travel_request_documents = []
        maximum_client_id = self.mongodb_database_connection.get_maximum_or_minimum(
            collection='travel_request')

        for i in range(0, number_of_travel_request_documents):
            client_id = maximum_client_id + 1
            maximum_client_id = client_id
            starting_bus_stop_index = random.randint(0,
                                                     number_of_bus_stops - 2)
            starting_bus_stop = bus_stops[starting_bus_stop_index]
            ending_bus_stop_index = random.randint(starting_bus_stop_index + 1,
                                                   number_of_bus_stops - 1)
            ending_bus_stop = bus_stops[ending_bus_stop_index]
            additional_departure_time_interval = random.randint(0, 59)
            departure_datetime = (
                random.choice(datetime_population) +
                timedelta(minutes=additional_departure_time_interval))

            travel_request_document = {
                'client_id': client_id,
                'bus_line_id': bus_line_id,
                'starting_bus_stop': starting_bus_stop,
                'ending_bus_stop': ending_bus_stop,
                'departure_datetime': departure_datetime,
                'arrival_datetime': None,
                'starting_timetable_entry_index': None,
                'ending_timetable_entry_index': None
            }
            travel_request_documents.append(travel_request_document)

        # 4: The generated travel_request_documents are stored at the
        #    TravelRequests collection of the System Database.
        #
        self.mongodb_database_connection.insert_travel_request_documents(
            travel_request_documents=travel_request_documents)
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     log(module_name='look_ahead_handler', log_type='DEBUG',
         log_message='mongodb_database_connection: established')
Ejemplo n.º 9
0
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     log(module_name='Router', log_type='DEBUG', log_message='mongodb_database_connection: established')
Ejemplo n.º 10
0
class MongodbDatabaseConnectionTester(object):
    def __init__(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='initialize_mongodb_database_connection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='initialize_mongodb_database_connection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_all_collections(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_all_collections: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_all_collections()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_all_collections: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_address_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_address_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_address_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_address_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_bus_line_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_line_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_line_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_line_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_bus_stop_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_stop_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_stop_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_stop_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_bus_stop_waypoints_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_stop_waypoints_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_stop_waypoints_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_bus_stop_waypoints_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_edge_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_edge_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_edge_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_edge_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_node_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_node_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_node_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_node_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_point_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_point_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_point_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_point_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_timetable_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_timetable_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_timetable_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_timetable_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_traffic_event_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_traffic_event_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_traffic_event_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_traffic_event_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_travel_request_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_travel_request_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_travel_request_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_travel_request_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def clear_way_documents_collection(self):
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_way_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_way_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='clear_way_documents_collection: finished - elapsed_time = ' +
                        str(self.elapsed_time) + ' sec')

    def print_address_documents(self, object_ids=None, names=None, node_ids=None, counter=None):
        """
        Print multiple address_documents.

        address_document: {'_id', 'name', 'node_id', 'point': {'longitude', 'latitude'}}

        :param object_ids: [ObjectId]
        :param names: [string]
        :param node_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_address_documents')
        self.mongodb_database_connection.print_address_documents(
            object_ids=object_ids,
            names=names,
            node_ids=node_ids,
            counter=counter
        )

    def print_bus_line_documents(self, object_ids=None, line_ids=None, counter=None):
        """
        Print multiple bus_line_documents.

        bus_line_document: {
            '_id', 'line_id', 'bus_stops': [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        }
        :param object_ids: [ObjectId]
        :param line_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_bus_line_documents')
        self.mongodb_database_connection.print_bus_line_documents(
            object_ids=object_ids,
            line_ids=line_ids,
            counter=counter
        )

    def print_bus_stop_documents(self, object_ids=None, osm_ids=None, names=None, counter=None):
        """
        Print multiple bus_stop_documents.

        bus_stop_document: {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param names: [string]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_bus_stop_documents')
        self.mongodb_database_connection.print_bus_stop_documents(
            object_ids=object_ids,
            osm_ids=osm_ids,
            names=names,
            counter=counter
        )

    def print_bus_stop_waypoints_documents(self, object_ids=None, bus_stops=None, bus_stop_names=None, line_id=None):
        """
        Print multiple bus_stop_waypoints_documents.

        bus_stop_waypoints_document: {
            '_id', 'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'waypoints': [[edge_object_id]]
        }
        :param object_ids: [ObjectId]
        :param bus_stops: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        :param bus_stop_names: [string]
        :param line_id: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_bus_stop_waypoints_documents')
        self.mongodb_database_connection.print_bus_stop_waypoints_documents(
            object_ids=object_ids,
            bus_stops=bus_stops,
            bus_stop_names=bus_stop_names,
            line_id=line_id
        )

    def print_detailed_bus_stop_waypoints_documents(self, object_ids=None, bus_stops=None,
                                                    bus_stop_names=None, line_id=None):
        """
        Print multiple detailed_bus_stop_waypoints_documents.

        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        bus_stop_waypoints_document: {
            '_id', 'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'waypoints': [[edge_object_id]]
        }
        detailed_bus_stop_waypoints_document: {
            '_id', 'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'waypoints': [[edge_document]]
        }
        :param object_ids: [ObjectId]
        :param bus_stops: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        :param bus_stop_names: [string]
        :param line_id: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_detailed_bus_stop_waypoints_documents')
        self.mongodb_database_connection.print_detailed_bus_stop_waypoints_documents(
            object_ids=object_ids,
            bus_stops=bus_stops,
            bus_stop_names=bus_stop_names,
            line_id=line_id
        )

    def print_edge_documents(self, object_ids=None, starting_node_osm_id=None, ending_node_osm_id=None, counter=None):
        """
        Print multiple edge_documents.

        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        :param object_ids: [ObjectId]
        :param starting_node_osm_id: int
        :param ending_node_osm_id: int
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_edge_documents')
        self.mongodb_database_connection.print_edge_documents(
            object_ids=object_ids,
            starting_node_osm_id=starting_node_osm_id,
            ending_node_osm_id=ending_node_osm_id,
            counter=counter
        )

    def print_node_documents(self, object_ids=None, osm_ids=None, counter=None):
        """
        Print multiple node_documents.

        node_document: {'_id', 'osm_id', 'tags', 'point': {'longitude', 'latitude'}}

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_node_documents')
        self.mongodb_database_connection.print_node_documents(
            object_ids=object_ids,
            osm_ids=osm_ids,
            counter=counter
        )

    def print_point_documents(self, object_ids=None, osm_ids=None, counter=None):
        """
        Print multiple point_documents.

        point_document: {'_id', 'osm_id', 'point': {'longitude', 'latitude'}}

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_point_documents')
        self.mongodb_database_connection.print_point_documents(
            object_ids=object_ids,
            osm_ids=osm_ids,
            counter=counter
        )

    def print_timetable_documents(self, object_ids=None, line_ids=None, counter=None, timetables_control=True,
                                  timetable_entries_control=False, travel_requests_control=False):
        """
        Print multiple timetable_documents.

        timetable_document: {
            '_id', 'line_id',
            'timetable_entries': [{
                'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
                'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
                'departure_datetime', 'arrival_datetime', 'total_time', 'number_of_onboarding_passengers',
                'number_of_deboarding_passengers', 'number_of_current_passengers'}],
            'travel_requests': [{
                '_id', 'client_id', 'line_id',
                'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
                'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
                'departure_datetime', 'arrival_datetime',
                'starting_timetable_entry_index', 'ending_timetable_entry_index'}]
        }
        :param object_ids: [ObjectId]
        :param line_ids: [int]
        :param counter: int
        :param timetables_control: bool
        :param timetable_entries_control: bool
        :param travel_requests_control: bool
        :return: timetable_documents: [timetable_document]
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_timetable_documents')
        self.mongodb_database_connection.print_timetable_documents(
            object_ids=object_ids,
            line_ids=line_ids,
            counter=counter,
            timetables_control=timetables_control,
            timetable_entries_control=timetable_entries_control,
            travel_requests_control=travel_requests_control
        )

    def print_traffic_density_documents(self, bus_stops=None, bus_stop_names=None):
        """
        Print multiple traffic_density_documents.

        traffic_density_document: {
            'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'traffic_density_values': [[{'edge_object_id', 'traffic_density'}]]
        }
        :param bus_stops: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        :param bus_stop_names: [string]
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_traffic_density_documents')
        self.mongodb_database_connection.print_traffic_density_documents(
            bus_stops=bus_stops,
            bus_stop_names=bus_stop_names
        )

    def print_travel_request_documents(self, object_ids=None, client_ids=None, line_ids=None,
                                       min_departure_datetime=None, max_departure_datetime=None,
                                       counter=None):
        """
        Print multiple travel_request_documents.

        travel_request_document: {
            '_id', 'client_id', 'line_id',
            'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'departure_datetime', 'arrival_datetime',
            'starting_timetable_entry_index', 'ending_timetable_entry_index'
        }
        :param object_ids: [ObjectId]
        :param client_ids: [int]
        :param line_ids: [int]
        :param min_departure_datetime: datetime
        :param max_departure_datetime: datetime
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_travel_request_documents')
        self.mongodb_database_connection.print_travel_request_documents(
            object_ids=object_ids,
            client_ids=client_ids,
            line_ids=line_ids,
            min_departure_datetime=min_departure_datetime,
            max_departure_datetime=max_departure_datetime,
            counter=counter
        )

    def print_way_documents(self, object_ids=None, osm_ids=None, counter=None):
        """
        Print multiple way_documents.

        way_document: {'_id', 'osm_id', 'tags', 'references'}

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test', log_type='INFO',
            log_message='print_way_documents')
        self.mongodb_database_connection.print_way_documents(
            object_ids=object_ids,
            osm_ids=osm_ids,
            counter=counter
        )
Ejemplo n.º 11
0
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     self.lowest_traffic_density_value = 0
     self.highest_traffic_density_value = 1
     log(module_name='traffic_data_simulator', log_type='DEBUG',
         log_message='mongodb_database_connection: established')
Ejemplo n.º 12
0
class TrafficDataSimulator(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        self.lowest_traffic_density_value = 0
        self.highest_traffic_density_value = 1
        log(module_name='traffic_data_simulator', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def clear_traffic_density(self):
        self.mongodb_database_connection.clear_traffic_density()

    def generate_traffic_data_between_two_bus_stops(self, starting_bus_stop=None, ending_bus_stop=None,
                                                    starting_bus_stop_name=None, ending_bus_stop_name=None):
        """
        Generate random traffic density values for the edges which connect two bus_stops.

        :param starting_bus_stop: bus_stop_document
        :param ending_bus_stop: bus_stop_document
        :param starting_bus_stop_name: string
        :param ending_bus_stop_name: string
        :return: None
        """
        bus_stop_waypoints_document = self.mongodb_database_connection.find_bus_stop_waypoints_document(
            starting_bus_stop=starting_bus_stop,
            ending_bus_stop=ending_bus_stop,
            starting_bus_stop_name=starting_bus_stop_name,
            ending_bus_stop_name=ending_bus_stop_name
        )
        edge_object_ids_included_in_bus_stop_waypoints_document = \
            self.mongodb_database_connection.get_edge_object_ids_included_in_bus_stop_waypoints(
                bus_stop_waypoints=bus_stop_waypoints_document
            )
        self.generate_traffic_data_for_edge_object_ids(
            edge_object_ids=edge_object_ids_included_in_bus_stop_waypoints_document
        )

    def generate_traffic_data_between_multiple_bus_stops(self, bus_stops=None, bus_stop_names=None):
        """
        Generate random traffic density values for the edges which connect multiple bus_stops.

        :param bus_stops: [bus_stop_documents]
        :param bus_stop_names: [string]
        :return: None
        """
        if bus_stops is not None:
            number_of_bus_stops = len(bus_stops)

            for i in range(0, number_of_bus_stops - 1):
                starting_bus_stop = bus_stops[i]
                ending_bus_stop = bus_stops[i + 1]
                self.generate_traffic_data_between_two_bus_stops(
                    starting_bus_stop=starting_bus_stop,
                    ending_bus_stop=ending_bus_stop
                )

        elif bus_stop_names is not None:
            number_of_bus_stop_names = len(bus_stop_names)

            for i in range(0, number_of_bus_stop_names - 1):
                starting_bus_stop_name = bus_stop_names[i]
                ending_bus_stop_name = bus_stop_names[i + 1]
                self.generate_traffic_data_between_two_bus_stops(
                    starting_bus_stop_name=starting_bus_stop_name,
                    ending_bus_stop_name=ending_bus_stop_name
                )

        else:
            pass

    def generate_traffic_data_for_bus_line(self, bus_line=None, bus_line_id=None):
        """
        Generate random traffic density values for the edge_documents which are included in a bus_line_document.

        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """
        edge_object_ids_included_in_bus_line_document = \
            self.mongodb_database_connection.get_edge_object_ids_included_in_bus_line(
                bus_line=bus_line,
                bus_line_id=bus_line_id
            )

        self.generate_traffic_data_for_edge_object_ids(
            edge_object_ids=edge_object_ids_included_in_bus_line_document
        )

    def generate_traffic_data_for_bus_lines(self, bus_lines=None):
        """
        Generate random traffic density values for the edge_documents which are included in a bus_line_documents.

        :param bus_lines: [bus_line_document]
        :return: None
        """
        if bus_lines is None:
            bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.generate_traffic_data_for_bus_line(bus_line=bus_line)

    def generate_traffic_data_for_edge_object_ids(self, edge_object_ids):
        """
        Generate random traffic density values and update the corresponding edge_documents.

        :param edge_object_ids: [ObjectId]
        :return: None
        """
        number_of_edge_object_ids = len(edge_object_ids)
        number_of_produced_traffic_values = random.randint(0, number_of_edge_object_ids - 1)

        for i in range(0, number_of_produced_traffic_values):
            # edge_object_ids_index = random.randint(0, number_of_edge_object_ids - 1)
            edge_object_ids_index = i
            edge_object_id = edge_object_ids[edge_object_ids_index]
            new_traffic_density_value = random.uniform(
                self.lowest_traffic_density_value,
                self.highest_traffic_density_value
            )
            self.mongodb_database_connection.update_traffic_density(
                edge_object_id=edge_object_id,
                new_traffic_density_value=new_traffic_density_value
            )

    def set_traffic_density_limits(self, lowest_traffic_density_value, highest_traffic_density_value):
        """
        Set the lowest and highest traffic density values.

        :param lowest_traffic_density_value: float: [0, 1]
        :param highest_traffic_density_value: float: [0, 1]
        :return: None
        """
        self.lowest_traffic_density_value = lowest_traffic_density_value
        self.highest_traffic_density_value = highest_traffic_density_value
class TrafficDataParser(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        self.edge_documents = []
        self.traffic_event_documents = []
        self.minimum_latitude = float('inf')
        self.maximum_latitude = float('-inf')
        self.minimum_longitude = float('inf')
        self.maximum_longitude = float('-inf')
        log(module_name='traffic_data_parser', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def check_borders_of_traffic_event_document(self, traffic_event_document):
        """
        Check if a traffic_event_document corresponds to the operation area, by comparing their borders.
        If yes, then return True. Otherwise, False.

        :param traffic_event_document: traffic_event_document
        :return: included_in_borders: bool
        """
        included_in_borders = True
        traffic_event_point_document = traffic_event_document.get('point')
        traffic_event_longitude = traffic_event_point_document.get('longitude')
        traffic_event_latitude = traffic_event_point_document.get('latitude')

        if (traffic_event_longitude < self.minimum_longitude or traffic_event_longitude > self.maximum_longitude or
                    traffic_event_latitude < self.minimum_latitude or traffic_event_latitude > self.maximum_latitude):
            included_in_borders = False

        return included_in_borders

    @staticmethod
    def estimate_traffic_density_value(event_level):
        """
        Estimate the traffic_density_value based on the event_level.

        :param event_level: int
        :return: traffic_density_value: float
        """
        if event_level == 1:
            traffic_density_value = 0.2
        elif event_level == 2:
            traffic_density_value = 0.4
        elif event_level == 3:
            traffic_density_value = 0.6
        elif event_level == 4:
            traffic_density_value = 0.8
        else:
            traffic_density_value = 0.0

        return traffic_density_value

    def get_borders_of_operation_area(self):
        """
        Get the minimum and maximum values for longitude and latitude of the operation area.

        :return: borders: {'minimum_latitude', 'maximum_latitude', 'minimum_longitude', 'maximum_longitude'}
        """
        if len(self.edge_documents) == 0:
            self.retrieve_edge_documents()

        self.set_borders_of_operation_area()

        borders = {
            'minimum_latitude': self.minimum_latitude,
            'maximum_latitude': self.maximum_latitude,
            'minimum_longitude': self.minimum_longitude,
            'maximum_longitude': self.maximum_longitude
        }
        return borders

    @staticmethod
    def get_edge_document_with_minimum_distance(traffic_event_document, edge_documents):
        """
        Get the edge_document which corresponds to the nearest point of a traffic_event.

        :param traffic_event_document: traffic_event_document
        :param edge_documents: [edge_document]
        :return:
        """
        edge_document_with_minimum_distance = None
        minimum_distance = float('Inf')

        traffic_event_point_document = traffic_event_document.get('point')
        traffic_event_longitude = traffic_event_point_document.get('longitude')
        traffic_event_latitude = traffic_event_point_document.get('latitude')

        traffic_event_point = Point(
            longitude=traffic_event_longitude,
            latitude=traffic_event_latitude
        )
        for edge_document in edge_documents:
            starting_node = edge_document.get('starting_node')
            starting_node_point_document = starting_node.get('point')
            starting_node_point = Point(
                longitude=starting_node_point_document.get('longitude'),
                latitude=starting_node_point_document.get('latitude')
            )
            ending_node = edge_document.get('ending_node')
            ending_node_point_document = ending_node.get('point')
            ending_node_point = Point(
                longitude=ending_node_point_document.get('longitude'),
                latitude=ending_node_point_document.get('latitude')
            )
            distance_of_starting_node = distance(
                point_one=traffic_event_point,
                point_two=starting_node_point
            )
            distance_of_ending_node = distance(
                point_one=traffic_event_point,
                point_two=ending_node_point
            )
            distance_of_edge_document = distance_of_starting_node + distance_of_ending_node

            if distance_of_edge_document < minimum_distance:
                edge_document_with_minimum_distance = edge_document
                minimum_distance = distance_of_edge_document

        return edge_document_with_minimum_distance

    def retrieve_edge_documents(self):
        self.edge_documents = self.mongodb_database_connection.find_edge_documents()

    def retrieve_traffic_event_documents(self):
        self.traffic_event_documents = self.mongodb_database_connection.find_traffic_event_documents()

    def set_borders_of_operation_area(self):
        """
        Set the minimum and maximum values for longitude and latitude of the operation area.

        :return: None
        """
        for edge_document in self.edge_documents:
            starting_node = edge_document.get('starting_node')
            starting_node_point_document = starting_node.get('point')
            starting_node_longitude = starting_node_point_document.get('longitude')
            starting_node_latitude = starting_node_point_document.get('latitude')

            if starting_node_longitude < self.minimum_longitude:
                self.minimum_longitude = starting_node_longitude

            if starting_node_longitude > self.maximum_longitude:
                self.maximum_longitude = starting_node_longitude

            if starting_node_latitude < self.minimum_latitude:
                self.minimum_latitude = starting_node_latitude

            if starting_node_latitude > self.maximum_latitude:
                self.maximum_latitude = starting_node_latitude

            ending_node = edge_document.get('ending_node')
            ending_node_point_document = ending_node.get('point')
            ending_node_longitude = ending_node_point_document.get('longitude')
            ending_node_latitude = ending_node_point_document.get('latitude')

            if ending_node_longitude < self.minimum_longitude:
                self.minimum_longitude = ending_node_longitude

            if ending_node_longitude > self.maximum_longitude:
                self.maximum_longitude = ending_node_longitude

            if ending_node_latitude < self.minimum_latitude:
                self.minimum_latitude = ending_node_latitude

            if ending_node_latitude > self.maximum_latitude:
                self.maximum_latitude = ending_node_latitude

    def update_traffic_data(self):
        """

        :return: None
        """
        self.retrieve_edge_documents()
        self.retrieve_traffic_event_documents()
        self.set_borders_of_operation_area()

        for traffic_event_document in self.traffic_event_documents:

            if self.check_borders_of_traffic_event_document(traffic_event_document=traffic_event_document):
                edge_document_with_minimum_distance = self.get_edge_document_with_minimum_distance(
                    traffic_event_document=traffic_event_document,
                    edge_documents=self.edge_documents
                )
                traffic_density_value = self.estimate_traffic_density_value(
                    event_level=traffic_event_document.get('event_level')
                )
                self.mongodb_database_connection.update_traffic_density(
                    edge_object_id=edge_document_with_minimum_distance.get('_id'),
                    new_traffic_density_value=traffic_density_value
                )
            else:
                print 'traffic_event_document: out_of_borders -', traffic_event_document
Ejemplo n.º 14
0
 def __init__(self):
     self.module_name = 'bus_vehicle_handler'
     self.log_type = 'DEBUG'
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     self.log_message = 'mongodb_database_connection: established'
     log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)
Ejemplo n.º 15
0
class BusVehicleHandler(object):
    def __init__(self):
        self.module_name = 'bus_vehicle_handler'
        self.log_type = 'DEBUG'
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        self.log_message = 'mongodb_database_connection: established'
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

    def clear_bus_vehicle_documents_collection(self):
        """
        Delete all the documents of the BusVehicleDocuments collection.

        :return: number_of_deleted_documents: int
        """
        number_of_deleted_documents = self.mongodb_database_connection.clear_bus_vehicle_documents_collection()
        self.log_message = 'clear_bus_vehicle_documents_collection: number_of_deleted_documents: ' + \
                           str(number_of_deleted_documents)
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

        return number_of_deleted_documents

    def delete_bus_vehicle_document(self, object_id=None, bus_vehicle_id=None):
        """
        Delete a bus_vehicle_document.

        :param object_id: ObjectId
        :param bus_vehicle_id: int
        :return: True if the document was successfully deleted, otherwise False.
        """
        deleted = self.delete_bus_vehicle_document(
            object_id=object_id,
            bus_vehicle_id=bus_vehicle_id
        )
        self.log_message = 'delete_bus_vehicle_document: ' + str(deleted)
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

        return deleted

    def delete_bus_vehicle_documents(self, object_ids=None, bus_vehicle_ids=None):
        """
        Delete multiple bus_vehicle_documents.

        :param object_ids: [ObjectId]
        :param bus_vehicle_ids: [int]
        :return: number_of_deleted_documents: int
        """
        number_of_deleted_documents = self.mongodb_database_connection.delete_bus_vehicle_documents(
            object_ids=object_ids,
            bus_vehicle_ids=bus_vehicle_ids
        )
        self.log_message = 'delete_bus_vehicle_documents: number_of_deleted_documents: ' + \
                           str(number_of_deleted_documents)
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

        return number_of_deleted_documents

    def generate_bus_vehicle_document(self, maximum_capacity):
        """
        Generate a new bus_vehicle_document.

        :param maximum_capacity: int
        :return: new_object_id: ObjectId
        """
        maximum_bus_vehicle_id = self.mongodb_database_connection.get_maximum_or_minimum(collection='bus_vehicle')
        bus_vehicle_id = maximum_bus_vehicle_id + 1

        bus_vehicle_document = {
            'bus_vehicle_id': bus_vehicle_id,
            'maximum_capacity': maximum_capacity,
            'routes': []
        }
        new_object_id = self.insert_bus_vehicle_document(bus_vehicle_document=bus_vehicle_document)
        return new_object_id

    def generate_bus_vehicle_documents(self, maximum_capacity, number_of_bus_vehicle_documents):
        """
        Generate multiple bus_vehicle_documents.

        :param maximum_capacity: int
        :param number_of_bus_vehicle_documents: int
        :return: new_object_ids: [ObjectIds]
        """
        bus_vehicle_documents = []
        maximum_bus_vehicle_id = self.mongodb_database_connection.get_maximum_or_minimum(collection='bus_vehicle')

        for i in range(0, number_of_bus_vehicle_documents):
            bus_vehicle_id = maximum_bus_vehicle_id + 1
            maximum_bus_vehicle_id = bus_vehicle_id

            bus_vehicle_document = {
                'bus_vehicle_id': bus_vehicle_id,
                'maximum_capacity': maximum_capacity,
                'routes': []
            }
            bus_vehicle_documents.append(bus_vehicle_document)

        new_object_ids = self.insert_bus_vehicle_documents(bus_vehicle_documents=bus_vehicle_documents)
        return new_object_ids

    def insert_bus_vehicle_document(self, bus_vehicle_document=None, bus_vehicle_id=None,
                                    maximum_capacity=None, routes=None):
        """
        Insert a new bus_vehicle_document or update, if it already exists in the database.

        :param bus_vehicle_document
        :param bus_vehicle_id: int
        :param maximum_capacity: int
        :param routes: [{'starting_datetime', 'ending_datetime', 'timetable_id'}]
        :return: new_object_id: ObjectId
        """
        new_object_id = self.mongodb_database_connection.insert_bus_vehicle_document(
            bus_vehicle_document=bus_vehicle_document,
            bus_vehicle_id=bus_vehicle_id,
            maximum_capacity=maximum_capacity,
            routes=routes
        )
        self.log_message = 'insert_bus_vehicle_document: new_object_id: ' + str(new_object_id)
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

        return new_object_id

    def insert_bus_vehicle_documents(self, bus_vehicle_documents, insert_many=False):
        """
        Insert multiple bus_vehicle_documents or update existing ones.

        :param bus_vehicle_documents:
        :param insert_many: bool
        :return: new_object_ids: [ObjectId]
        """
        new_object_ids = self.mongodb_database_connection.insert_bus_vehicle_documents(
            bus_vehicle_documents=bus_vehicle_documents,
            insert_many=insert_many
        )
        self.log_message = 'insert_bus_vehicle_documents: new_object_ids: ' + str(new_object_ids)
        log(module_name=self.module_name, log_type=self.log_type, log_message=self.log_message)

        return new_object_ids

    def print_bus_vehicle_document(self, object_id=None, bus_vehicle_id=None):
        """
        Print a bus_vehicle_document.

        :param object_id: ObjectId
        :param bus_vehicle_id: int
        :return: None
        """
        self.mongodb_database_connection.print_bus_vehicle_document(
            object_id=object_id,
            bus_vehicle_id=bus_vehicle_id
        )

    def print_bus_vehicle_documents(self, object_ids=None, bus_vehicle_ids=None, counter=None):
        """
        Print multiple bus_vehicle_documents.

        :param object_ids: [ObjectId]
        :param bus_vehicle_ids: [int]
        :param counter: int
        :return: None
        """
        self.mongodb_database_connection.print_bus_vehicle_documents(
            object_ids=object_ids,
            bus_vehicle_ids=bus_vehicle_ids,
            counter=counter
        )
Ejemplo n.º 16
0
class LookAheadHandler(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(
            host=mongodb_host, port=mongodb_port)
        log(module_name='look_ahead_handler',
            log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def generate_bus_line(self, bus_stop_names, bus_line_id=None):
        """
        Generate a bus_line, consisted of a bus_line_id and a list of bus_stops, and store it to the corresponding
        collection of the System Database. Moreover, identify all the possible waypoints between the bus_stops
        of the bus_line, and populate the BusStopWaypoints collection.

        :param bus_stop_names: [string]
        :param bus_line_id: int
        :return: None
        """
        # 1: The inputs: bus_line_id and bus_stop_names are provided to the function, so as as a bus_line
        #    with the corresponding bus_line_id and bus_stops to be generated.
        #
        # 2: The Look Ahead connects to the System Database and retrieves the bus_stops which correspond to
        #    the provided bus_stop_names. The function returns None and the bus_line is not generated,
        #    in case there is a bus_stop_name which does not correspond to a stored bus_stop.
        #
        if bus_line_id is None:
            maximum_bus_line_id = self.mongodb_database_connection.get_maximum_or_minimum(
                collection='bus_line')
            bus_line_id = maximum_bus_line_id + 1

        bus_stops = []

        for bus_stop_name in bus_stop_names:
            bus_stop_document = self.mongodb_database_connection.find_bus_stop_document(
                name=bus_stop_name)

            if bus_stop_document is None:
                log_message = 'find_bus_stop_document (mongodb_database) - name:', bus_stop_name, '- result: None'
                log(module_name='look_ahead_handler',
                    log_type='DEBUG',
                    log_message=log_message)
                return None
            else:
                bus_stops.append(bus_stop_document)

        # 3: The intermediate waypoints of the bus_routes, which are generated while combining starting and
        #    ending bus_stops of the bus_line, should be stored as bus_stop_waypoints_documents at the System Database.
        #    The Look Ahead checks the existing bus_stop_waypoints_documents and communicates with the Route Generator
        #    in order to identify the waypoints of the bus_routes which are not already stored. The newly generated
        #    bus_stop_waypoints_documents are getting stored to the corresponding collection of the System Database.
        #    The function returns None and the bus_line is not generated, in case the Route Generator can not identify
        #    a possible route in order to connect the bus_stops of the bus_line.
        #
        number_of_bus_stops = len(bus_stops)

        for i in range(0, number_of_bus_stops - 1):
            starting_bus_stop = bus_stops[i]
            ending_bus_stop = bus_stops[i + 1]

            bus_stop_waypoints_document = self.mongodb_database_connection.find_bus_stop_waypoints_document(
                starting_bus_stop=starting_bus_stop,
                ending_bus_stop=ending_bus_stop)
            if bus_stop_waypoints_document is None:
                route_generator_response = get_waypoints_between_two_bus_stops(
                    starting_bus_stop=starting_bus_stop,
                    ending_bus_stop=ending_bus_stop)
                if route_generator_response is None:
                    log(module_name='look_ahead_handler',
                        log_type='DEBUG',
                        log_message=
                        'get_waypoints_between_two_bus_stops (route_generator): None'
                        )
                    return None
                else:
                    waypoints = route_generator_response.get('waypoints')

                    if len(waypoints) == 0:
                        log(module_name='look_ahead_handler',
                            log_type='DEBUG',
                            log_message=
                            'get_waypoints_between_two_bus_stops (route_generator): None'
                            )
                        return None

                    lists_of_edge_object_ids = []

                    for list_of_edges in waypoints:
                        list_of_edge_object_ids = []

                        for edge in list_of_edges:
                            edge_object_id = edge.get('_id')
                            list_of_edge_object_ids.append(edge_object_id)

                        lists_of_edge_object_ids.append(
                            list_of_edge_object_ids)

                    # waypoints: [[edge_object_id]]
                    #
                    waypoints = lists_of_edge_object_ids

                    self.mongodb_database_connection.insert_bus_stop_waypoints_document(
                        starting_bus_stop=starting_bus_stop,
                        ending_bus_stop=ending_bus_stop,
                        waypoints=waypoints)

        # 4: The Look Ahead stores the newly generated bus_line_document, which is consisted of the bus_line_id
        #    and the list of bus_stops, to the corresponding collection of the System Database.
        #    In case there is an already existing bus_line_document, with the same bus_line_id,
        #    then the list of bus_stops gets updated.
        #
        bus_line_document = {
            'bus_line_id': bus_line_id,
            'bus_stops': bus_stops
        }
        self.mongodb_database_connection.insert_bus_line_document(
            bus_line_document=bus_line_document)

        log(module_name='look_ahead_handler',
            log_type='DEBUG',
            log_message='insert_bus_line_document (mongodb_database): ok')

    def generate_timetables_for_bus_line(self,
                                         timetables_starting_datetime,
                                         timetables_ending_datetime,
                                         requests_min_departure_datetime,
                                         requests_max_departure_datetime,
                                         bus_line=None,
                                         bus_line_id=None):
        """
        Generate timetables for a bus_line, for a selected datetime period,
        evaluating travel_requests of a specific datetime period.

        - The input: timetables_starting_datetime and input: timetables_ending_datetime
          are provided to the function, so as timetables for the specific datetime period
          to be generated.

        - The input: requests_min_departure_datetime and input: requests_max_departure_datetime
          are provided to the function, so as travel_requests with departure_datetime corresponding
          to the the specific datetime period to be evaluated.

        - The input: bus_line or input: bus_line_id is provided to the function,
          so as timetables for the specific bus_line to be generated.

        :param timetables_starting_datetime: datetime
        :param timetables_ending_datetime: datetime
        :param requests_min_departure_datetime: datetime
        :param requests_max_departure_datetime: datetime
        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """

        maximum_timetable_id_in_database = self.mongodb_database_connection.get_maximum_or_minimum(
            collection='timetable')

        # 1: The list of bus_stops corresponding to the provided bus_line is retrieved.
        #
        # bus_stop_document: {
        #     '_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}
        # }
        # bus_stops: [bus_stop_document]
        #
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(
                bus_line_id=bus_line_id)
        else:
            bus_line_id = bus_line.get('bus_line_id')

        bus_stops = bus_line.get('bus_stops')

        # 2: The Look Ahead retrieves from the System Database the travel_requests with
        #    departure_datetime higher than requests_min_departure_datetime and
        #    lower than requests_max_departure_datetime.
        #
        # travel_request_document: {
        #     '_id', 'client_id', 'bus_line_id',
        #     'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
        #     'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
        #     'departure_datetime', 'arrival_datetime'
        # }
        # travel_requests: [travel_request_document]
        #
        travel_requests = self.mongodb_database_connection.find_travel_request_documents(
            bus_line_ids=[bus_line_id],
            min_departure_datetime=requests_min_departure_datetime,
            max_departure_datetime=requests_max_departure_datetime)

        # 3: (TimetableGenerator is initialized) The Look Ahead sends a request to the Route Generator so as
        #    to identify the less time-consuming bus_route between the bus_stops of bus_line,
        #    while taking into consideration the current levels of traffic density.
        #
        timetable_generator = TimetableGenerator(
            maximum_timetable_id_in_database=maximum_timetable_id_in_database,
            bus_line_id=bus_line_id,
            bus_stops=bus_stops,
            travel_requests=travel_requests)

        # The list of bus_stops of a bus_line might contain the same bus_stop_osm_ids more than once.
        # For this reason, each travel_request needs to be related with the correct index in the bus_stops list.
        # So, the values 'starting_timetable_entry_index' and 'ending_timetable_entry_index' are estimated.
        #
        correspond_travel_requests_to_bus_stops(
            travel_requests=timetable_generator.travel_requests,
            bus_stops=timetable_generator.bus_stops)

        # 4: Based on the response of the Route Generator, which includes details about the followed bus_route,
        #    and using only one bus vehicle, the Look Ahead generates some initial timetables which cover the
        #    whole datetime period from timetables_starting_datetime to timetables_ending_datetime.
        #    Initially, the list of travel requests of these timetables is empty, and the departure_datetime and
        #    arrival_datetime values of the timetable_entries are based exclusively on the details of the bus_route.
        #    In the next steps of the algorithm, these timetables are used in the initial clustering
        #    of the travel requests.
        #
        timetable_generator.timetables = generate_initial_timetables(
            bus_line_id=bus_line_id,
            timetables_starting_datetime=timetables_starting_datetime,
            timetables_ending_datetime=timetables_ending_datetime,
            route_generator_response=timetable_generator.
            route_generator_response)

        current_average_waiting_time_of_timetables = float('Inf')

        while True:
            new_timetables = generate_new_timetables_based_on_travel_requests(
                current_timetables=timetable_generator.timetables,
                travel_requests=timetable_generator.travel_requests)
            new_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
                timetables=new_timetables)
            if new_average_waiting_time_of_timetables < current_average_waiting_time_of_timetables:
                timetable_generator.timetables = new_timetables
                current_average_waiting_time_of_timetables = new_average_waiting_time_of_timetables
                print_timetables(timetables=timetable_generator.timetables)
            else:
                break

        print_timetables(timetables=timetable_generator.timetables)

        self.mongodb_database_connection.delete_timetable_documents(
            bus_line_id=bus_line.get('bus_line_id'))
        self.mongodb_database_connection.insert_timetable_documents(
            timetable_documents=timetable_generator.timetables)
        log(module_name='look_ahead_handler',
            log_type='DEBUG',
            log_message='insert_timetable_documents (mongodb_database): ok')

    def generate_timetables_for_bus_lines(self, timetables_starting_datetime,
                                          timetables_ending_datetime,
                                          requests_min_departure_datetime,
                                          requests_max_departure_datetime):
        """
        Generate timetables for all bus_lines, for a selected datetime period,
        evaluating travel_requests of a specific datetime period.

        :param timetables_starting_datetime: datetime
        :param timetables_ending_datetime: datetime
        :param requests_min_departure_datetime: datetime
        :param requests_max_departure_datetime: datetime
        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.generate_timetables_for_bus_line(
                bus_line=bus_line,
                timetables_starting_datetime=timetables_starting_datetime,
                timetables_ending_datetime=timetables_ending_datetime,
                requests_min_departure_datetime=requests_min_departure_datetime,
                requests_max_departure_datetime=requests_max_departure_datetime
            )

    def update_timetables_of_bus_line(self, bus_line=None, bus_line_id=None):
        """
        Update the timetables of a bus_line, taking into consideration the current levels of traffic_density.

        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(
                bus_line_id=bus_line_id)
        else:
            bus_line_id = bus_line.get('bus_line_id')

        bus_stops = bus_line.get('bus_stops')
        timetables = self.mongodb_database_connection.find_timetable_documents(
            bus_line_ids=[bus_line_id])
        travel_requests = get_travel_requests_of_timetables(
            timetables=timetables)

        timetable_updater = TimetableUpdater(bus_stops=bus_stops,
                                             timetables=timetables,
                                             travel_requests=travel_requests)
        update_entries_of_timetables(
            timetables=timetable_updater.timetables,
            route_generator_response=timetable_updater.route_generator_response
        )
        current_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
            timetables=timetable_updater.timetables)
        print_timetables(timetables=timetable_updater.timetables)

        while True:
            new_timetables = generate_new_timetables_based_on_travel_requests(
                current_timetables=timetable_updater.timetables,
                travel_requests=timetable_updater.travel_requests)
            new_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
                timetables=new_timetables)
            if new_average_waiting_time_of_timetables < current_average_waiting_time_of_timetables:
                timetable_updater.timetables = new_timetables
                current_average_waiting_time_of_timetables = new_average_waiting_time_of_timetables
                print_timetables(timetables=timetable_updater.timetables)
            else:
                break

        print_timetables(timetables=timetable_updater.timetables)

        self.mongodb_database_connection.delete_timetable_documents(
            bus_line_id=bus_line.get('bus_line_id'))
        self.mongodb_database_connection.insert_timetable_documents(
            timetable_documents=timetable_updater.timetables)
        log(module_name='look_ahead_handler',
            log_type='DEBUG',
            log_message='update_timetable_documents (mongodb_database): ok')

    def update_timetables_of_bus_lines(self):
        """
        Update the timetables of all bus_lines, taking into consideration the current levels of traffic_density.

        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.update_timetables_of_bus_line(bus_line=bus_line)
Ejemplo n.º 17
0
class OsmParser(object):
    relations = None
    ways_filter = None
    nodes_filter = None
    relations_filter = None

    def __init__(self, osm_filename):
        """
        :param osm_filename: Directory of the input OSM file.
        :type osm_filename: string
        """
        self.osm_filename = osm_filename
        self.address_documents_dictionary = {}
        self.bus_stop_documents_dictionary = {}
        self.edge_documents_dictionary = {}
        self.node_documents_dictionary = {}
        self.point_documents_dictionary = {}
        self.way_documents_dictionary = {}
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(module_name='osm_parser', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def add_address(self, name, node_id, point):
        """
        Add an address to the address_documents_dictionary.

        :type name: string
        :type node_id: int
        :type point: Point
        """
        if name is None or name == '' or node_id is None or point is None:
            return

        if name not in self.address_documents_dictionary:
            self.address_documents_dictionary[name] = Address(name, node_id, point)
        else:
            self.address_documents_dictionary[name].add_node(node_id=node_id, point=point)

    def add_bus_stop(self, osm_id, name, point):
        """
        Add a bus_stop to the bus_stop_names dictionary.

        :type osm_id: int
        :type name: string
        :type point: {'longitude', 'latitude'}
        """
        bus_stop_document = {'osm_id': osm_id, 'name': name, 'point': point}
        self.bus_stop_documents_dictionary[osm_id] = bus_stop_document

    def add_edge(self, starting_node, ending_node, max_speed, road_type, way_id, traffic_density=None):
        """
        Add an edge to the edge_documents_dictionary.

        :param starting_node: {'osm_id', 'point': {'longitude', 'latitude'}}
        :param ending_node: {'osm_id', 'point': {'longitude', 'latitude'}}
        :type max_speed: float or int
        :type road_type: string
        :param way_id: osm_id: int
        :param traffic_density: A value between 0 and 1 indicating the density of traffic: float
        """
        if traffic_density is None:
            traffic_density = 0

        starting_node_osm_id = starting_node.get('osm_id')
        edge_document = {'starting_node': starting_node, 'ending_node': ending_node, 'max_speed': max_speed,
                         'road_type': road_type, 'way_id': way_id, 'traffic_density': traffic_density}

        if starting_node_osm_id in self.edge_documents_dictionary:
            self.edge_documents_dictionary[starting_node_osm_id].append(edge_document)
        else:
            self.edge_documents_dictionary[starting_node_osm_id] = [edge_document]

    def add_node(self, osm_id, tags, point):
        """
        Add a node to the node_documents_dictionary.

        :type osm_id: int
        :type tags: {}
        :type point: {'longitude', 'latitude'}
        """
        node_document = {'osm_id': osm_id, 'tags': tags, 'point': point}
        self.node_documents_dictionary[osm_id] = node_document

    def add_point(self, osm_id, point):
        """
        Add a point to the point_documents_dictionary.

        :type osm_id: int
        :type point: {'longitude': longitude, 'latitude': latitude}
        """
        point_document = {'osm_id': osm_id, 'point': point}
        self.point_documents_dictionary[osm_id] = point_document

    def add_way(self, osm_id, tags, references):
        """
        Add a way to the way_documents_dictionary.

        :type osm_id: int
        :type tags: {}
        :param references: [osm_id]
        """
        way_document = {'osm_id': osm_id, 'tags': tags, 'references': references}
        self.way_documents_dictionary[osm_id] = way_document

    @staticmethod
    def address_range(number):
        """
        Turn address number format into a range. E.g. '1A-1C' to '1A','1B','1C'.

        :param number: string
        :return: generator
        """
        regular_expression = re.compile(
            '''
            ((?P<starting_address_number>(\d+))
            (?P<starting_address_letter> ([a-zA-Z]*))
            \s*-\s*
            (?P<ending_address_number>(\d+))
            (?P<ending_address_letter>([a-zA-Z]*)))
            ''',
            re.VERBOSE
        )
        match = regular_expression.search(number)

        if match:
            starting_number = match.groupdict()['starting_address_number']
            starting_letter = match.groupdict()['starting_address_letter']
            ending_number = match.groupdict()['ending_address_number']
            ending_letter = match.groupdict()['ending_address_letter']

            if starting_letter and ending_letter:
                for c in xrange(ord(starting_letter), ord(ending_letter) + 1):
                    yield '' + starting_number + chr(c)
            elif starting_number and ending_number:
                for c in xrange(int(starting_number), int(ending_number) + 1):
                    yield c
            else:
                yield '' + starting_number + starting_letter
        else:
            numbers = number.split(',')

            if len(numbers) > 1:
                for num in numbers:
                    yield num.strip()
            else:
                yield number

    def get_list_of_addresses(self):
        list_of_addresses = []

        for name, address in self.address_documents_dictionary.iteritems():
            for node_id, point in address.nodes:
                document = {'name': name, 'node_id': node_id,
                            'point': {'longitude': point.longitude, 'latitude': point.latitude}}
                list_of_addresses.append(document)

        return list_of_addresses

    def get_list_of_bus_stops(self):
        """
        Retrieve a list containing all the bus_stop documents.

        :return: [{'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        """
        list_of_bus_stops = self.bus_stop_documents_dictionary.values()
        return list_of_bus_stops

    def get_list_of_edges(self):
        """
        Retrieve a list containing all the edge_documents_dictionary documents.

        :return: [{'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                   'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                   'max_speed', 'road_type', 'way_id', 'traffic_density'}]
        """
        list_of_edges = []

        for starting_node_edges in self.edge_documents_dictionary.values():
            for edge in starting_node_edges:
                list_of_edges.append(edge)

        return list_of_edges

    def get_list_of_nodes(self):
        """
        Retrieve a list containing all the node documents.

        :return: [{'osm_id', 'tags', 'point': {'longitude', 'latitude'}}]
        """
        list_of_nodes = self.node_documents_dictionary.values()
        return list_of_nodes

    def get_list_of_points(self):
        """
        Retrieve a list containing all the point documents.

        :return: [{'osm_id', 'point': {'longitude', 'latitude'}}]
        """
        list_of_points = self.point_documents_dictionary.values()
        return list_of_points

    def get_list_of_ways(self):
        """
        Retrieve a list containing all the way documents.

        :return: [{'osm_id', 'tags', 'references'}]
        """
        list_of_ways = self.way_documents_dictionary.values()
        return list_of_ways

    def get_point_from_osm_id(self, osm_id):
        """
        Retrieve the point which corresponds to a specific osm_id.

        :type osm_id: int
        :return: Point
        """
        point = None
        # {'osm_id', 'point': {'longitude', 'latitude'}}
        point_document = self.point_documents_dictionary.get(osm_id)

        if point_document is not None:
            point_entry = point_document.get('point')
            point = Point(longitude=point_entry.get('longitude'), latitude=point_entry.get('latitude'))

        return point

    def get_point_coordinates_from_osm_id(self, osm_id):
        """
        Retrieve the {'longitude', 'latitude'} values which correspond to a specific osm_id.

        :type osm_id: int
        :return: {'longitude', 'latitude'}
        """
        point_coordinates = None
        # {'osm_id', 'point': {'longitude', 'latitude'}}
        point_document = self.point_documents_dictionary.get(osm_id)

        if point_document is not None:
            point_coordinates = point_document.get('point')

        return point_coordinates

    def parse_osm_file(self):
        osm_parser = OSMParser(
            concurrency=2,
            coords_callback=self.parse_points,
            nodes_callback=self.parse_nodes,
            ways_callback=self.parse_ways,
            # relations_ callback=self.relations,
            # nodes_tag_filter=self.nodes_filter,
            # ways_tag_filter=self.ways_filter,
            # relations_tag_filter=self.relations_filter
        )
        osm_parser.parse(self.osm_filename)

    def parse_address(self, osm_id, tags, point):
        """
        Parse the name, the street, and the house numbers which are related to an address, and add them to the
        address_documents_dictionary along with their corresponding osm_id and point.

        :type osm_id: int
        :param tags: {}
        :param point: Point
        """
        name = tags.get('name', '')
        street = tags.get('addr:street', '')
        house_number = tags.get('addr:housenumber', '')

        if name != '':
            self.add_address(name=name, node_id=osm_id, point=point)

        if street != '' and house_number != '':
            for num in self.address_range(house_number):
                # num = str(num)
                try:
                    num = str(num)
                except UnicodeEncodeError:
                    num = ''
                address = street + ' ' + num
                self.add_address(name=address, node_id=osm_id, point=point)

    def parse_edges(self, osm_id, tags, references):
        """
        Parse the edges which connect the nodes, bus_stops, and points of the map.

        :param osm_id: Corresponds to the osm_id of the way.
        :type osm_id: int
        :type tags: {}
        :param references: [osm_id] The list of osm_id objects which are connected to each other.
        :type references: [int]
        """
        oneway = tags.get('oneway', '') in ('yes', 'true', '1')
        max_speed = tags.get('maxspeed', standard_speed)
        road_type = tags.get('highway')

        for reference_index in range(len(references) - 1):
            starting_node_osm_id = references[reference_index]
            starting_node_point = self.get_point_coordinates_from_osm_id(osm_id=starting_node_osm_id)

            ending_node_osm_id = references[reference_index + 1]
            ending_node_point = self.get_point_coordinates_from_osm_id(osm_id=ending_node_osm_id)

            if (starting_node_point is None) or (ending_node_point is None):
                continue

            starting_node = {'osm_id': starting_node_osm_id, 'point': starting_node_point}
            ending_node = {'osm_id': ending_node_osm_id, 'point': ending_node_point}

            self.add_edge(starting_node=starting_node, ending_node=ending_node,
                          max_speed=max_speed, road_type=road_type, way_id=osm_id)

            if not oneway:
                self.add_edge(starting_node=ending_node, ending_node=starting_node,
                              max_speed=max_speed, road_type=road_type, way_id=osm_id)

    def parse_nodes(self, nodes):
        """
        Parse the list of nodes and populate the corresponding dictionary.
        Parse the list of bus stops, which are included in the nodes, and populate the corresponding dictionary.
        Parse the list of addresses, where the nodes correspond to, and populate the corresponding dictionary.

        :type nodes: [(osm_id, tags, (longitude, latitude))]
        """
        for node in nodes:
            osm_id, tags, (longitude, latitude) = node

            point = {'longitude': longitude, 'latitude': latitude}
            self.add_node(osm_id=osm_id, tags=tags, point=point)

            bus = tags.get('bus')
            highway = tags.get('highway')
            name = tags.get('name')
            public_transport = tags.get('public_transport')

            if (bus == 'yes' or highway == 'bus_stop' or public_transport == 'platform' or
                        public_transport == 'stop_area') and name:
                self.add_bus_stop(osm_id=osm_id, name=tags.get('name'), point=point)

            point = Point(longitude=longitude, latitude=latitude)
            self.parse_address(osm_id=osm_id, tags=tags, point=point)

    def parse_points(self, coordinates):
        """
        Parse the list of point_documents_dictionary and populate the corresponding dictionary.

        :param coordinates: [(osm_id, longitude, latitude)]
        :type coordinates: [(int, float, float)]
        """
        for osm_id, longitude, latitude in coordinates:
            point = {'longitude': longitude, 'latitude': latitude}
            self.add_point(osm_id=osm_id, point=point)

    def parse_ways(self, ways):
        """
        Parse the list of way_documents_dictionary and populate the corresponding dictionary
        with the ones that can be accessed by bus vehicles.

        :type ways: [()]
        """
        for way in ways:
            osm_id, tags, references = way

            if tags.get('motorcar') != 'no' and tags.get('highway') in bus_road_types:
                self.add_way(osm_id=osm_id, tags=tags, references=references)
                self.parse_edges(osm_id=osm_id, tags=tags, references=references)

            name = tags.get('name', '')
            if name != '':
                for reference in references:
                    point = self.get_point_from_osm_id(osm_id=reference)
                    self.add_address(name=name, node_id=reference, point=point)

    def populate_address_documents_collection(self):
        address_documents = self.get_list_of_addresses()
        number_of_address_documents = len(address_documents)
        self.mongodb_database_connection.insert_address_documents(address_documents=address_documents)
        self.address_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_address_documents_collection (mongodb_database) ok - '
                        'Number of new address_documents: ' + str(number_of_address_documents))

    def populate_bus_stop_documents_collection(self):
        bus_stop_documents = self.get_list_of_bus_stops()
        number_of_bus_stop_documents = len(bus_stop_documents)
        self.mongodb_database_connection.insert_bus_stop_documents(bus_stop_documents=bus_stop_documents)
        self.bus_stop_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_bus_stop_documents_collection (mongodb_database) ok - '
                        'Number of new bus_stop_documents: ' + str(number_of_bus_stop_documents))

    def populate_edge_documents_collection(self):
        edge_documents = self.get_list_of_edges()
        number_of_edge_documents = len(edge_documents)
        self.mongodb_database_connection.insert_edge_documents(edge_documents=edge_documents)
        self.edge_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_edge_documents_collection (mongodb_database) ok - '
                        'Number of new edge_documents: ' + str(number_of_edge_documents))

    def populate_node_documents_collection(self):
        node_documents = self.get_list_of_nodes()
        number_of_node_documents = len(node_documents)
        self.mongodb_database_connection.insert_node_documents(node_documents=node_documents)
        self.node_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_node_documents_collection (mongodb_database) ok - '
                        'Number of new node_documents: ' + str(number_of_node_documents))

    def populate_point_documents_collection(self):
        point_documents = self.get_list_of_points()
        number_of_point_documents = len(point_documents)
        self.mongodb_database_connection.insert_point_documents(point_documents=point_documents)
        self.point_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_point_documents_collection (mongodb_database) ok - '
                        'Number of new point_documents: ' + str(number_of_point_documents))

    def populate_way_documents_collection(self):
        way_documents = self.get_list_of_ways()
        number_of_way_documents = len(way_documents)
        self.mongodb_database_connection.insert_way_documents(way_documents=way_documents)
        self.way_documents_dictionary = {}
        log(module_name='osm_parser_tester', log_type='DEBUG',
            log_message='populate_way_documents_collection (mongodb_database) ok - '
                        'Number of new way_documents: ' + str(number_of_way_documents))

    def populate_all_collections(self):
        self.populate_address_documents_collection()
        self.populate_bus_stop_documents_collection()
        self.populate_edge_documents_collection()
        self.populate_node_documents_collection()
        self.populate_point_documents_collection()
        self.populate_way_documents_collection()
class MongodbDatabaseConnectionTester(object):
    def __init__(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='initialize_mongodb_database_connection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection = MongodbDatabaseConnection(
            host=mongodb_host, port=mongodb_port)
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'initialize_mongodb_database_connection: finished - elapsed_time = '
            + str(self.elapsed_time) + ' sec')

    def clear_all_collections(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_all_collections: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_all_collections()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_all_collections: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_address_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_address_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_address_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_address_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_bus_line_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_bus_line_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_line_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_bus_line_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_bus_stop_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_bus_stop_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_stop_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_bus_stop_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_bus_stop_waypoints_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_bus_stop_waypoints_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_bus_stop_waypoints_documents_collection(
        )
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_bus_stop_waypoints_documents_collection: finished - elapsed_time = '
            + str(self.elapsed_time) + ' sec')

    def clear_edge_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_edge_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_edge_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_edge_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_node_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_node_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_node_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_node_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_point_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_point_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_point_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_point_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_timetable_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_timetable_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_timetable_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_timetable_documents_collection: finished - elapsed_time = '
            + str(self.elapsed_time) + ' sec')

    def clear_traffic_density(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_traffic_density: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_traffic_density()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_traffic_density: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def clear_traffic_event_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_traffic_event_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_traffic_event_documents_collection(
        )
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_traffic_event_documents_collection: finished - elapsed_time = '
            + str(self.elapsed_time) + ' sec')

    def clear_travel_request_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_travel_request_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_travel_request_documents_collection(
        )
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_travel_request_documents_collection: finished - elapsed_time = '
            + str(self.elapsed_time) + ' sec')

    def clear_way_documents_collection(self):
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='clear_way_documents_collection: starting')
        self.start_time = time.time()
        self.mongodb_database_connection.clear_way_documents_collection()
        self.elapsed_time = time.time() - self.start_time
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message=
            'clear_way_documents_collection: finished - elapsed_time = ' +
            str(self.elapsed_time) + ' sec')

    def print_address_documents(self,
                                object_ids=None,
                                names=None,
                                node_ids=None,
                                counter=None):
        """
        Print multiple address_documents.

        :param object_ids: [ObjectId]
        :param names: [string]
        :param node_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_address_documents')
        self.mongodb_database_connection.print_address_documents(
            object_ids=object_ids,
            names=names,
            node_ids=node_ids,
            counter=counter)

    def print_bus_line_documents(self,
                                 object_ids=None,
                                 bus_line_ids=None,
                                 counter=None):
        """
        Print multiple bus_line_documents.

        :param object_ids: [ObjectId]
        :param bus_line_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_bus_line_documents')
        self.mongodb_database_connection.print_bus_line_documents(
            object_ids=object_ids, bus_line_ids=bus_line_ids, counter=counter)

    def print_bus_stop_documents(self,
                                 object_ids=None,
                                 osm_ids=None,
                                 names=None,
                                 counter=None):
        """
        Print multiple bus_stop_documents.

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param names: [string]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_bus_stop_documents')
        self.mongodb_database_connection.print_bus_stop_documents(
            object_ids=object_ids,
            osm_ids=osm_ids,
            names=names,
            counter=counter)

    def print_bus_stop_waypoints_documents(self,
                                           object_ids=None,
                                           bus_stops=None,
                                           bus_stop_names=None,
                                           bus_line_id=None):
        """
        Print multiple bus_stop_waypoints_documents.

        :param object_ids: [ObjectId]
        :param bus_stops: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        :param bus_stop_names: [string]
        :param bus_line_id: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_bus_stop_waypoints_documents')
        self.mongodb_database_connection.print_bus_stop_waypoints_documents(
            object_ids=object_ids,
            bus_stops=bus_stops,
            bus_stop_names=bus_stop_names,
            bus_line_id=bus_line_id)

    def print_detailed_bus_stop_waypoints_documents(self,
                                                    object_ids=None,
                                                    bus_stops=None,
                                                    bus_stop_names=None,
                                                    bus_line_id=None):
        """
        Print multiple detailed_bus_stop_waypoints_documents.

        :param object_ids: [ObjectId]
        :param bus_stops: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        :param bus_stop_names: [string]
        :param bus_line_id: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_detailed_bus_stop_waypoints_documents')
        self.mongodb_database_connection.print_detailed_bus_stop_waypoints_documents(
            object_ids=object_ids,
            bus_stops=bus_stops,
            bus_stop_names=bus_stop_names,
            bus_line_id=bus_line_id)

    def print_edge_documents(self,
                             object_ids=None,
                             starting_node_osm_id=None,
                             ending_node_osm_id=None,
                             counter=None):
        """
        Print multiple edge_documents.

        :param object_ids: [ObjectId]
        :param starting_node_osm_id: int
        :param ending_node_osm_id: int
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_edge_documents')
        self.mongodb_database_connection.print_edge_documents(
            object_ids=object_ids,
            starting_node_osm_id=starting_node_osm_id,
            ending_node_osm_id=ending_node_osm_id,
            counter=counter)

    def print_node_documents(self,
                             object_ids=None,
                             osm_ids=None,
                             counter=None):
        """
        Print multiple node_documents.

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_node_documents')
        self.mongodb_database_connection.print_node_documents(
            object_ids=object_ids, osm_ids=osm_ids, counter=counter)

    def print_point_documents(self,
                              object_ids=None,
                              osm_ids=None,
                              counter=None):
        """
        Print multiple point_documents.

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_point_documents')
        self.mongodb_database_connection.print_point_documents(
            object_ids=object_ids, osm_ids=osm_ids, counter=counter)

    def print_timetable_documents(self,
                                  object_ids=None,
                                  bus_line_ids=None,
                                  counter=None,
                                  timetables_control=True,
                                  timetable_entries_control=False,
                                  travel_requests_control=False):
        """
        Print multiple timetable_documents.

        :param object_ids: [ObjectId]
        :param bus_line_ids: [int]
        :param counter: int
        :param timetables_control: bool
        :param timetable_entries_control: bool
        :param travel_requests_control: bool
        :return: timetable_documents: [timetable_document]
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_timetable_documents')
        self.mongodb_database_connection.print_timetable_documents(
            object_ids=object_ids,
            bus_line_ids=bus_line_ids,
            counter=counter,
            timetables_control=timetables_control,
            timetable_entries_control=timetable_entries_control,
            travel_requests_control=travel_requests_control)

    def print_traffic_density_documents(self,
                                        bus_stops=None,
                                        bus_stop_names=None):
        """
        Print multiple traffic_density_documents.

        :param bus_stops: [bus_stop_document]
        :param bus_stop_names: [string]
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_traffic_density_documents')
        self.mongodb_database_connection.print_traffic_density_documents(
            bus_stops=bus_stops, bus_stop_names=bus_stop_names)

    def print_travel_request_documents(self,
                                       object_ids=None,
                                       client_ids=None,
                                       bus_line_ids=None,
                                       min_departure_datetime=None,
                                       max_departure_datetime=None,
                                       counter=None):
        """
        Print multiple travel_request_documents.

        :param object_ids: [ObjectId]
        :param client_ids: [int]
        :param bus_line_ids: [int]
        :param min_departure_datetime: datetime
        :param max_departure_datetime: datetime
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_travel_request_documents')
        self.mongodb_database_connection.print_travel_request_documents(
            object_ids=object_ids,
            client_ids=client_ids,
            bus_line_ids=bus_line_ids,
            min_departure_datetime=min_departure_datetime,
            max_departure_datetime=max_departure_datetime,
            counter=counter)

    def print_way_documents(self, object_ids=None, osm_ids=None, counter=None):
        """
        Print multiple way_documents.

        :param object_ids: [ObjectId]
        :param osm_ids: [int]
        :param counter: int
        :return: None
        """
        log(module_name='mongodb_database_connection_test',
            log_type='INFO',
            log_message='print_way_documents')
        self.mongodb_database_connection.print_way_documents(
            object_ids=object_ids, osm_ids=osm_ids, counter=counter)
Ejemplo n.º 19
0
class Router(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(module_name='Router', log_type='DEBUG', log_message='mongodb_database_connection: established')

    def get_bus_stop(self, name=None, provided_point=None, longitude=None, latitude=None):
        """
        Get a bus_stop_document.

        :param name: string
        :param provided_point: Point
        :param longitude: float
        :param latitude: float
        :return: bus_stop: bus_stop_document
        """
        bus_stop = None

        if name is not None:
            bus_stop = self.mongodb_database_connection.find_bus_stop_document(name=name)
        elif provided_point is not None:
            bus_stop_documents = self.mongodb_database_connection.find_bus_stop_documents()
            bus_stop = self.get_bus_stop_closest_to_point(
                bus_stop_documents=bus_stop_documents,
                provided_point=provided_point
            )
        elif longitude is not None and latitude is not None:
            point = Point(longitude=longitude, latitude=latitude)
            bus_stop_documents = self.mongodb_database_connection.find_bus_stop_documents()
            bus_stop = self.get_bus_stop_closest_to_point(
                bus_stop_documents=bus_stop_documents,
                provided_point=point
            )
        else:
            pass

        return bus_stop

    @staticmethod
    def get_bus_stop_closest_to_point(bus_stop_documents, provided_point):
        """
        Get the bus stop which is closest to a geographic point.

        :param bus_stop_documents: [bus_stop_document]
        :param provided_point: Point
        :return closest_bus_stop: bus_stop_document
        """
        minimum_distance = float('Inf')
        closest_bus_stop = None

        for bus_stop_document in bus_stop_documents:
            bus_stop_document_point = bus_stop_document.get('point')

            current_distance = distance(
                point_one=provided_point,
                longitude_two=bus_stop_document_point.get('longitude'),
                latitude_two=bus_stop_document_point.get('latitude')
            )
            if current_distance == 0:
                closest_bus_stop = bus_stop_document
                break
            elif current_distance < minimum_distance:
                minimum_distance = current_distance
                closest_bus_stop = bus_stop_document
            else:
                pass

        return closest_bus_stop

    def get_bus_stops(self, names):
        """
        Get multiple bus_stop_documents.

        :param names: [string]
        :return: bus_stops: [bus_stop_document]
        """
        bus_stops = []

        # for name in names:
        #     bus_stop = self.get_bus_stop(name=name)
        #     bus_stops.append(bus_stop)

        bus_stop_documents = self.mongodb_database_connection.find_bus_stop_documents(names=names)
        bus_stop_documents_dictionary = {}

        for bus_stop_document in bus_stop_documents:
            bus_stop_document_name = bus_stop_document.get('name')
            bus_stop_documents_dictionary[bus_stop_document_name] = bus_stop_document

        for name in names:
            bus_stop_document = bus_stop_documents_dictionary.get(name)
            bus_stops.append(bus_stop_document)

        return bus_stops

    def get_bus_stops_dictionary(self):
        """
        Retrieve a dictionary containing all the documents of the BusStops collection.

        :return: bus_stops_dictionary: {name -> {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}}
        """
        bus_stops_dictionary = self.mongodb_database_connection.find_bus_stop_documents(in_dictionary=True)
        return bus_stops_dictionary

    def get_bus_stops_list(self):
        """
        Retrieve a list containing all the documents of the BusStops collection.

        :return: bus_stops_list: [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        """
        bus_stops_list = self.mongodb_database_connection.find_bus_stop_documents()
        return bus_stops_list

    def get_edges_dictionary(self):
        """
        Retrieve a dictionary containing all the documents of the Edges collection.

        :return: {starting_node_osm_id -> [{'_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                                            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                                            'max_speed', 'road_type', 'way_id', 'traffic_density'}]}
        """
        edges_dictionary = self.mongodb_database_connection.find_edge_documents(in_dictionary=True)
        return edges_dictionary

    def get_edges_list(self):
        """
        Retrieve a list containing all the documents of the Edges collection.

        :return: edges_list: [{'_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                               'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
                               'max_speed', 'road_type', 'way_id', 'traffic_density'}]
        """
        edges_list = self.mongodb_database_connection.find_edge_documents()
        return edges_list

    def get_points_dictionary(self):
        """
        Retrieve a dictionary containing all the documents of the Points collection.

        :return points_dictionary: {osm_id -> {'_id', 'osm_id', 'point': {'longitude', 'latitude'}}}
        """
        points_dictionary = self.mongodb_database_connection.find_point_documents(in_dictionary=True)
        return points_dictionary

    def get_route_between_two_bus_stops(self, starting_bus_stop=None, ending_bus_stop=None,
                                        starting_bus_stop_name=None, ending_bus_stop_name=None,
                                        edges_dictionary=None):
        """
        Identify the less time-consuming route between two bus_stops.

        :param starting_bus_stop: bus_stop_document
        :param ending_bus_stop: bus_stop_document
        :param starting_bus_stop_name: string
        :param ending_bus_stop_name: string
        :param edges_dictionary: {starting_node_osm_id -> [edge_document]}
        :return response: get_route_between_two_bus_stops
        """
        if starting_bus_stop is None and starting_bus_stop_name is not None:
            starting_bus_stop = self.get_bus_stop(name=starting_bus_stop_name)

        if ending_bus_stop is None and ending_bus_stop_name is not None:
            ending_bus_stop = self.get_bus_stop(name=ending_bus_stop_name)

        if edges_dictionary is None:
            edges_dictionary = self.get_edges_dictionary()

        route = identify_path_with_lowest_cost(
            start=starting_bus_stop,
            end=ending_bus_stop,
            edges_dictionary=edges_dictionary
        )
        response = {
            'starting_bus_stop': starting_bus_stop,
            'ending_bus_stop': ending_bus_stop,
            'route': route
        }
        return response

    def get_route_between_multiple_bus_stops(self, bus_stops=None, bus_stop_names=None):
        """
        Identify the less time-consuming route between multiple bus_stops.

        :param bus_stops: [bus_stop_document]
        :param bus_stop_names: string
        :return response: get_route_between_multiple_bus_stops
        """
        response = []
        edges_dictionary = self.get_edges_dictionary()

        if bus_stops is None and bus_stop_names is not None:
            bus_stops = self.get_bus_stops(names=bus_stop_names)

        for i in range(0, len(bus_stops) - 1):
            starting_bus_stop = bus_stops[i]
            ending_bus_stop = bus_stops[i + 1]

            intermediate_route = self.get_route_between_two_bus_stops(
                starting_bus_stop=starting_bus_stop,
                ending_bus_stop=ending_bus_stop,
                edges_dictionary=edges_dictionary
            )
            response.append(intermediate_route)

        return response

    def get_waypoints_between_two_bus_stops(self, starting_bus_stop=None, ending_bus_stop=None,
                                            starting_bus_stop_name=None, ending_bus_stop_name=None):
        """
        Identify all possible route connections between two bus_stops.

        :param starting_bus_stop: bus_stop_document
        :param ending_bus_stop: bus_stop_document
        :param starting_bus_stop_name: string
        :param ending_bus_stop_name: string
        :return response: get_waypoints_between_two_bus_stops
        """
        if starting_bus_stop is None and starting_bus_stop_name is not None:
            starting_bus_stop = self.get_bus_stop(name=starting_bus_stop_name)

        if ending_bus_stop is None and ending_bus_stop_name is not None:
            ending_bus_stop = self.get_bus_stop(name=ending_bus_stop_name)

        edges_dictionary = self.get_edges_dictionary()

        waypoints = identify_all_paths(
            starting_node_osm_id=starting_bus_stop.get('osm_id'),
            ending_node_osm_id=ending_bus_stop.get('osm_id'),
            edges_dictionary=edges_dictionary
        )
        response = {
            'starting_bus_stop': starting_bus_stop,
            'ending_bus_stop': ending_bus_stop,
            'waypoints': waypoints
        }
        return response

    def get_waypoints_between_multiple_bus_stops(self, bus_stops=None, bus_stop_names=None):
        """
        Identify all possible route connections between multiple bus_stops.

        :param bus_stops: [bus_stop_document]
        :param bus_stop_names: string
        :return response: get_waypoints_between_multiple_bus_stops
        """
        response = []

        if bus_stops is None and bus_stop_names is not None:
            bus_stops = self.get_bus_stops(names=bus_stop_names)

        edges_dictionary = self.get_edges_dictionary()

        for i in range(0, len(bus_stops) - 1):
            starting_bus_stop = bus_stops[i]
            ending_bus_stop = bus_stops[i + 1]

            waypoints = identify_all_paths(
                starting_node_osm_id=starting_bus_stop.get('osm_id'),
                ending_node_osm_id=ending_bus_stop.get('osm_id'),
                edges_dictionary=edges_dictionary
            )
            intermediate_response = {
                'starting_bus_stop': starting_bus_stop,
                'ending_bus_stop': ending_bus_stop,
                'waypoints': waypoints
            }
            response.append(intermediate_response)

        return response
Ejemplo n.º 20
0
class TrafficDataSimulator(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(module_name='traffic_data_simulator', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def clear_traffic_density(self):
        self.mongodb_database_connection.clear_traffic_density()

    def generate_traffic_data_between_two_bus_stops(self, starting_bus_stop=None, ending_bus_stop=None,
                                                    starting_bus_stop_name=None, ending_bus_stop_name=None):
        """
        Generate random traffic density values for the edges which connect two bus_stops.

        bus_stop_document: {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}

        bus_stop_waypoints_document: {
            '_id', 'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'waypoints': [[edge_object_id]]
        }
        :param starting_bus_stop: bus_stop_document
        :param ending_bus_stop: bus_stop_document
        :param starting_bus_stop_name: string
        :param ending_bus_stop_name: string
        :return: None
        """
        bus_stop_waypoints_document = self.mongodb_database_connection.find_bus_stop_waypoints_document(
            starting_bus_stop=starting_bus_stop,
            ending_bus_stop=ending_bus_stop,
            starting_bus_stop_name=starting_bus_stop_name,
            ending_bus_stop_name=ending_bus_stop_name
        )
        edge_object_ids_included_in_bus_stop_waypoints_document = \
            self.mongodb_database_connection.get_edge_object_ids_included_in_bus_stop_waypoints(
                bus_stop_waypoints=bus_stop_waypoints_document
            )
        self.generate_traffic_data_for_edge_object_ids(
            edge_object_ids=edge_object_ids_included_in_bus_stop_waypoints_document
        )

    def generate_traffic_data_between_multiple_bus_stops(self, bus_stops=None, bus_stop_names=None):
        """
        Generate random traffic density values for the edges which connect multiple bus_stops.

        bus_stop_document: {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}

        :param bus_stops: [bus_stop_documents]
        :param bus_stop_names: [string]
        :return: None
        """
        if bus_stops is not None:
            number_of_bus_stops = len(bus_stops)

            for i in range(0, number_of_bus_stops - 1):
                starting_bus_stop = bus_stops[i]
                ending_bus_stop = bus_stops[i + 1]
                self.generate_traffic_data_between_two_bus_stops(
                    starting_bus_stop=starting_bus_stop,
                    ending_bus_stop=ending_bus_stop
                )

        elif bus_stop_names is not None:
            number_of_bus_stop_names = len(bus_stop_names)

            for i in range(0, number_of_bus_stop_names - 1):
                starting_bus_stop_name = bus_stop_names[i]
                ending_bus_stop_name = bus_stop_names[i + 1]
                self.generate_traffic_data_between_two_bus_stops(
                    starting_bus_stop_name=starting_bus_stop_name,
                    ending_bus_stop_name=ending_bus_stop_name
                )

        else:
            pass

    def generate_traffic_data_for_bus_line(self, bus_line=None, line_id=None):
        """
        Generate random traffic density values for the edge_documents which are included in a bus_line_document.

        bus_line_document: {
            '_id', 'line_id', 'bus_stops': [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        }
        :param bus_line: bus_line_document
        :param line_id: int
        :return: None
        """
        edge_object_ids_included_in_bus_line_document = \
            self.mongodb_database_connection.get_edge_object_ids_included_in_bus_line(
                bus_line=bus_line,
                line_id=line_id
            )

        self.generate_traffic_data_for_edge_object_ids(
            edge_object_ids=edge_object_ids_included_in_bus_line_document
        )

    def generate_traffic_data_for_bus_lines(self, bus_lines=None):
        """
        Generate random traffic density values for the edge_documents which are included in a bus_line_documents.

        bus_line_document: {
            '_id', 'line_id', 'bus_stops': [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        }
        :param bus_lines: [bus_line_document]
        :return: None
        """
        if bus_lines is None:
            bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.generate_traffic_data_for_bus_line(bus_line=bus_line)

    def generate_traffic_data_for_edge_object_ids(self, edge_object_ids):
        """
        Generate random traffic density values and update the corresponding edge_documents.

        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        :param edge_object_ids: [ObjectId]
        :return: None
        """
        number_of_edge_object_ids = len(edge_object_ids)
        number_of_produced_traffic_values = random.randint(0, number_of_edge_object_ids - 1)

        for i in range(0, number_of_produced_traffic_values):
            edge_object_ids_index = random.randint(0, number_of_edge_object_ids - 1)
            edge_object_id = edge_object_ids[edge_object_ids_index]
            new_traffic_density_value = random.uniform(0, 1)
            self.mongodb_database_connection.update_traffic_density(
                edge_object_id=edge_object_id,
                new_traffic_density_value=new_traffic_density_value
            )
class TravelRequestsSimulator(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(
            module_name="travel_requests_simulator",
            log_type="DEBUG",
            log_message="mongodb_database_connection: established",
        )

    def clear_travel_requests_collection(self):
        """
        Clear all the documents of the TravelRequests collection.

        :return: None
        """
        self.mongodb_database_connection.clear_travel_request_documents_collection()
        log(
            module_name="travel_requests_simulator",
            log_type="DEBUG",
            log_message="clear_travel_request_documents_collection: ok",
        )

    def delete_travel_request_documents(
        self, object_ids=None, client_ids=None, line_ids=None, min_departure_datetime=None, max_departure_datetime=None
    ):
        """
        Delete multiple travel_request_documents.

        travel_request_document: {
            '_id', 'client_id', 'line_id',
            'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
            'departure_datetime', 'arrival_datetime',
            'starting_timetable_entry_index', 'ending_timetable_entry_index'
        }
        :param object_ids: [ObjectId]
        :param client_ids: [int]
        :param line_ids: [int]
        :param min_departure_datetime: datetime
        :param max_departure_datetime
        :return: None
        """
        self.mongodb_database_connection.delete_travel_request_documents(
            object_ids=object_ids,
            client_ids=client_ids,
            line_ids=line_ids,
            min_departure_datetime=min_departure_datetime,
            max_departure_datetime=max_departure_datetime,
        )
        log(
            module_name="travel_requests_simulator", log_type="DEBUG", log_message="delete_travel_request_documents: ok"
        )

    def generate_random_travel_request_documents(
        self, initial_datetime, min_number_of_travel_request_documents, max_number_of_travel_request_documents
    ):
        """
        Generate random number of travel_request_documents for each bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        bus_line_document: {
            '_id', 'line_id', 'bus_stops': [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        }
        :param initial_datetime: datetime
        :param min_number_of_travel_request_documents: int
        :param max_number_of_travel_request_documents: int
        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            number_of_travel_request_documents = random.randint(
                min_number_of_travel_request_documents, max_number_of_travel_request_documents
            )
            self.generate_travel_request_documents(
                initial_datetime=initial_datetime,
                number_of_travel_request_documents=number_of_travel_request_documents,
                bus_line=bus_line,
            )

    def generate_travel_request_documents(
        self, initial_datetime, number_of_travel_request_documents, bus_line=None, line_id=None
    ):
        """
        Generate a specific number of travel_request_documents, for the selected bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        bus_line_document: {
            '_id', 'line_id', 'bus_stops': [{'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}}]
        }
        :param initial_datetime: datetime
        :param number_of_travel_request_documents: int
        :param bus_line: bus_line_document
        :param line_id: int
        :return: None
        """
        # 1: The inputs: initial_datetime, number_of_travel_request_documents, and (bus_line or line_id)
        #    are provided to the Travel Requests Simulator, so as a specific number of travel_request_documents
        #    to be generated, for the selected bus_line, for a 24hour period starting from
        #    the selected datetime.
        #
        # 2: If the provided bus_line is None, then the Travel Requests Simulator retrieves from the System Database
        #    the bus_line which corresponds to the provided line_id.
        #
        if bus_line is None and line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(line_id=line_id)
        else:
            pass

        bus_stops = bus_line.get("bus_stops")
        number_of_bus_stops = len(bus_stops)

        # 3: The Travel Requests Simulator generates the travel_request_documents, taking into consideration
        #    the variation of transportation demand during the hours of the day.
        #
        weighted_datetimes = [
            (initial_datetime + timedelta(hours=0), 1),
            (initial_datetime + timedelta(hours=1), 1),
            (initial_datetime + timedelta(hours=2), 1),
            (initial_datetime + timedelta(hours=3), 1),
            (initial_datetime + timedelta(hours=4), 1),
            (initial_datetime + timedelta(hours=5), 1),
            (initial_datetime + timedelta(hours=6), 1),
            (initial_datetime + timedelta(hours=7), 1),
            (initial_datetime + timedelta(hours=8), 1),
            (initial_datetime + timedelta(hours=9), 1),
            (initial_datetime + timedelta(hours=10), 1),
            (initial_datetime + timedelta(hours=11), 1),
            (initial_datetime + timedelta(hours=12), 1),
            (initial_datetime + timedelta(hours=13), 1),
            (initial_datetime + timedelta(hours=14), 1),
            (initial_datetime + timedelta(hours=15), 1),
            (initial_datetime + timedelta(hours=16), 1),
            (initial_datetime + timedelta(hours=17), 1),
            (initial_datetime + timedelta(hours=18), 1),
            (initial_datetime + timedelta(hours=19), 1),
            (initial_datetime + timedelta(hours=20), 1),
            (initial_datetime + timedelta(hours=21), 1),
            (initial_datetime + timedelta(hours=22), 1),
            (initial_datetime + timedelta(hours=23), 1),
        ]
        datetime_population = [val for val, cnt in weighted_datetimes for i in range(cnt)]
        travel_request_documents = []

        for i in range(0, number_of_travel_request_documents):
            client_id = i
            starting_bus_stop_index = random.randint(0, number_of_bus_stops - 2)
            starting_bus_stop = bus_stops[starting_bus_stop_index]
            ending_bus_stop_index = random.randint(starting_bus_stop_index + 1, number_of_bus_stops - 1)
            ending_bus_stop = bus_stops[ending_bus_stop_index]
            additional_departure_time_interval = random.randint(0, 59)
            departure_datetime = random.choice(datetime_population) + timedelta(
                minutes=additional_departure_time_interval
            )

            travel_request_document = {
                "client_id": client_id,
                "line_id": line_id,
                "starting_bus_stop": starting_bus_stop,
                "ending_bus_stop": ending_bus_stop,
                "departure_datetime": departure_datetime,
                "arrival_datetime": None,
                "starting_timetable_entry_index": None,
                "ending_timetable_entry_index": None,
            }
            travel_request_documents.append(travel_request_document)

        # 4: The generated travel_request_documents are stored at the
        #    TravelRequests collection of the System Database.
        #
        self.mongodb_database_connection.insert_travel_request_documents(
            travel_request_documents=travel_request_documents
        )
Ejemplo n.º 22
0
 def __init__(self):
     self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
     log(module_name='traffic_data_simulator', log_type='DEBUG',
         log_message='mongodb_database_connection: established')
class LookAheadHandler(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(module_name='look_ahead_handler', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def generate_bus_line(self, bus_stop_names, bus_line_id=None):
        """
        Generate a bus_line, consisted of a bus_line_id and a list of bus_stops, and store it to the corresponding
        collection of the System Database. Moreover, identify all the possible waypoints between the bus_stops
        of the bus_line, and populate the BusStopWaypoints collection.

        :param bus_stop_names: [string]
        :param bus_line_id: int
        :return: None
        """
        # 1: The inputs: bus_line_id and bus_stop_names are provided to the function, so as as a bus_line
        #    with the corresponding bus_line_id and bus_stops to be generated.
        #
        # 2: The Look Ahead connects to the System Database and retrieves the bus_stops which correspond to
        #    the provided bus_stop_names. The function returns None and the bus_line is not generated,
        #    in case there is a bus_stop_name which does not correspond to a stored bus_stop.
        #
        if bus_line_id is None:
            maximum_bus_line_id = self.mongodb_database_connection.get_maximum_or_minimum(collection='bus_line')
            bus_line_id = maximum_bus_line_id + 1

        bus_stops = []

        for bus_stop_name in bus_stop_names:
            bus_stop_document = self.mongodb_database_connection.find_bus_stop_document(name=bus_stop_name)

            if bus_stop_document is None:
                log_message = 'find_bus_stop_document (mongodb_database) - name:', bus_stop_name, '- result: None'
                log(module_name='look_ahead_handler', log_type='DEBUG', log_message=log_message)
                return None
            else:
                bus_stops.append(bus_stop_document)

        # 3: The intermediate waypoints of the bus_routes, which are generated while combining starting and
        #    ending bus_stops of the bus_line, should be stored as bus_stop_waypoints_documents at the System Database.
        #    The Look Ahead checks the existing bus_stop_waypoints_documents and communicates with the Route Generator
        #    in order to identify the waypoints of the bus_routes which are not already stored. The newly generated
        #    bus_stop_waypoints_documents are getting stored to the corresponding collection of the System Database.
        #    The function returns None and the bus_line is not generated, in case the Route Generator can not identify
        #    a possible route in order to connect the bus_stops of the bus_line.
        #
        number_of_bus_stops = len(bus_stops)

        for i in range(0, number_of_bus_stops - 1):
            starting_bus_stop = bus_stops[i]
            ending_bus_stop = bus_stops[i + 1]

            bus_stop_waypoints_document = self.mongodb_database_connection.find_bus_stop_waypoints_document(
                starting_bus_stop=starting_bus_stop,
                ending_bus_stop=ending_bus_stop
            )
            if bus_stop_waypoints_document is None:
                route_generator_response = get_waypoints_between_two_bus_stops(
                    starting_bus_stop=starting_bus_stop,
                    ending_bus_stop=ending_bus_stop
                )
                if route_generator_response is None:
                    log(module_name='look_ahead_handler', log_type='DEBUG',
                        log_message='get_waypoints_between_two_bus_stops (route_generator): None')
                    return None
                else:
                    waypoints = route_generator_response.get('waypoints')

                    if len(waypoints) == 0:
                        log(module_name='look_ahead_handler', log_type='DEBUG',
                            log_message='get_waypoints_between_two_bus_stops (route_generator): None')
                        return None

                    lists_of_edge_object_ids = []

                    for list_of_edges in waypoints:
                        list_of_edge_object_ids = []

                        for edge in list_of_edges:
                            edge_object_id = edge.get('_id')
                            list_of_edge_object_ids.append(edge_object_id)

                        lists_of_edge_object_ids.append(list_of_edge_object_ids)

                    # waypoints: [[edge_object_id]]
                    #
                    waypoints = lists_of_edge_object_ids

                    self.mongodb_database_connection.insert_bus_stop_waypoints_document(
                        starting_bus_stop=starting_bus_stop,
                        ending_bus_stop=ending_bus_stop,
                        waypoints=waypoints
                    )

        # 4: The Look Ahead stores the newly generated bus_line_document, which is consisted of the bus_line_id
        #    and the list of bus_stops, to the corresponding collection of the System Database.
        #    In case there is an already existing bus_line_document, with the same bus_line_id,
        #    then the list of bus_stops gets updated.
        #
        bus_line_document = {'bus_line_id': bus_line_id, 'bus_stops': bus_stops}
        self.mongodb_database_connection.insert_bus_line_document(bus_line_document=bus_line_document)

        log(module_name='look_ahead_handler', log_type='DEBUG',
            log_message='insert_bus_line_document (mongodb_database): ok')

    def generate_timetables_for_bus_line(self, timetables_starting_datetime, timetables_ending_datetime,
                                         requests_min_departure_datetime, requests_max_departure_datetime,
                                         bus_line=None, bus_line_id=None):
        """
        Generate timetables for a bus_line, for a selected datetime period,
        evaluating travel_requests of a specific datetime period.

        - The input: timetables_starting_datetime and input: timetables_ending_datetime
          are provided to the function, so as timetables for the specific datetime period
          to be generated.

        - The input: requests_min_departure_datetime and input: requests_max_departure_datetime
          are provided to the function, so as travel_requests with departure_datetime corresponding
          to the the specific datetime period to be evaluated.

        - The input: bus_line or input: bus_line_id is provided to the function,
          so as timetables for the specific bus_line to be generated.

        :param timetables_starting_datetime: datetime
        :param timetables_ending_datetime: datetime
        :param requests_min_departure_datetime: datetime
        :param requests_max_departure_datetime: datetime
        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """

        maximum_timetable_id_in_database = self.mongodb_database_connection.get_maximum_or_minimum(
            collection='timetable'
        )

        # 1: The list of bus_stops corresponding to the provided bus_line is retrieved.
        #
        # bus_stop_document: {
        #     '_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}
        # }
        # bus_stops: [bus_stop_document]
        #
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(bus_line_id=bus_line_id)
        else:
            bus_line_id = bus_line.get('bus_line_id')

        bus_stops = bus_line.get('bus_stops')

        # 2: The Look Ahead retrieves from the System Database the travel_requests with
        #    departure_datetime higher than requests_min_departure_datetime and
        #    lower than requests_max_departure_datetime.
        #
        # travel_request_document: {
        #     '_id', 'client_id', 'bus_line_id',
        #     'starting_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
        #     'ending_bus_stop': {'_id', 'osm_id', 'name', 'point': {'longitude', 'latitude'}},
        #     'departure_datetime', 'arrival_datetime'
        # }
        # travel_requests: [travel_request_document]
        #
        travel_requests = self.mongodb_database_connection.find_travel_request_documents(
            bus_line_ids=[bus_line_id],
            min_departure_datetime=requests_min_departure_datetime,
            max_departure_datetime=requests_max_departure_datetime
        )

        # 3: (TimetableGenerator is initialized) The Look Ahead sends a request to the Route Generator so as
        #    to identify the less time-consuming bus_route between the bus_stops of bus_line,
        #    while taking into consideration the current levels of traffic density.
        #
        timetable_generator = TimetableGenerator(
            maximum_timetable_id_in_database=maximum_timetable_id_in_database,
            bus_line_id=bus_line_id,
            bus_stops=bus_stops,
            travel_requests=travel_requests
        )

        # The list of bus_stops of a bus_line might contain the same bus_stop_osm_ids more than once.
        # For this reason, each travel_request needs to be related with the correct index in the bus_stops list.
        # So, the values 'starting_timetable_entry_index' and 'ending_timetable_entry_index' are estimated.
        #
        correspond_travel_requests_to_bus_stops(
            travel_requests=timetable_generator.travel_requests,
            bus_stops=timetable_generator.bus_stops
        )

        # 4: Based on the response of the Route Generator, which includes details about the followed bus_route,
        #    and using only one bus vehicle, the Look Ahead generates some initial timetables which cover the
        #    whole datetime period from timetables_starting_datetime to timetables_ending_datetime.
        #    Initially, the list of travel requests of these timetables is empty, and the departure_datetime and
        #    arrival_datetime values of the timetable_entries are based exclusively on the details of the bus_route.
        #    In the next steps of the algorithm, these timetables are used in the initial clustering
        #    of the travel requests.
        #
        timetable_generator.timetables = generate_initial_timetables(
            bus_line_id=bus_line_id,
            timetables_starting_datetime=timetables_starting_datetime,
            timetables_ending_datetime=timetables_ending_datetime,
            route_generator_response=timetable_generator.route_generator_response
        )

        current_average_waiting_time_of_timetables = float('Inf')

        while True:
            new_timetables = generate_new_timetables_based_on_travel_requests(
                current_timetables=timetable_generator.timetables,
                travel_requests=timetable_generator.travel_requests
            )
            new_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
                timetables=new_timetables
            )
            if new_average_waiting_time_of_timetables < current_average_waiting_time_of_timetables:
                timetable_generator.timetables = new_timetables
                current_average_waiting_time_of_timetables = new_average_waiting_time_of_timetables
                print_timetables(timetables=timetable_generator.timetables)
            else:
                break

        print_timetables(timetables=timetable_generator.timetables)

        self.mongodb_database_connection.delete_timetable_documents(
            bus_line_id=bus_line.get('bus_line_id')
        )
        self.mongodb_database_connection.insert_timetable_documents(
            timetable_documents=timetable_generator.timetables
        )
        log(module_name='look_ahead_handler', log_type='DEBUG',
            log_message='insert_timetable_documents (mongodb_database): ok')

    def generate_timetables_for_bus_lines(self, timetables_starting_datetime, timetables_ending_datetime,
                                          requests_min_departure_datetime, requests_max_departure_datetime):
        """
        Generate timetables for all bus_lines, for a selected datetime period,
        evaluating travel_requests of a specific datetime period.

        :param timetables_starting_datetime: datetime
        :param timetables_ending_datetime: datetime
        :param requests_min_departure_datetime: datetime
        :param requests_max_departure_datetime: datetime
        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.generate_timetables_for_bus_line(
                bus_line=bus_line,
                timetables_starting_datetime=timetables_starting_datetime,
                timetables_ending_datetime=timetables_ending_datetime,
                requests_min_departure_datetime=requests_min_departure_datetime,
                requests_max_departure_datetime=requests_max_departure_datetime
            )

    def update_timetables_of_bus_line(self, bus_line=None, bus_line_id=None):
        """
        Update the timetables of a bus_line, taking into consideration the current levels of traffic_density.

        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(bus_line_id=bus_line_id)
        else:
            bus_line_id = bus_line.get('bus_line_id')

        bus_stops = bus_line.get('bus_stops')
        timetables = self.mongodb_database_connection.find_timetable_documents(bus_line_ids=[bus_line_id])
        travel_requests = get_travel_requests_of_timetables(timetables=timetables)

        timetable_updater = TimetableUpdater(
            bus_stops=bus_stops,
            timetables=timetables,
            travel_requests=travel_requests
        )
        update_entries_of_timetables(
            timetables=timetable_updater.timetables,
            route_generator_response=timetable_updater.route_generator_response
        )
        current_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
            timetables=timetable_updater.timetables
        )
        print_timetables(timetables=timetable_updater.timetables)

        while True:
            new_timetables = generate_new_timetables_based_on_travel_requests(
                current_timetables=timetable_updater.timetables,
                travel_requests=timetable_updater.travel_requests
            )
            new_average_waiting_time_of_timetables = calculate_average_waiting_time_of_timetables_in_seconds(
                timetables=new_timetables
            )
            if new_average_waiting_time_of_timetables < current_average_waiting_time_of_timetables:
                timetable_updater.timetables = new_timetables
                current_average_waiting_time_of_timetables = new_average_waiting_time_of_timetables
                print_timetables(timetables=timetable_updater.timetables)
            else:
                break

        print_timetables(timetables=timetable_updater.timetables)

        self.mongodb_database_connection.delete_timetable_documents(
            bus_line_id=bus_line.get('bus_line_id')
        )
        self.mongodb_database_connection.insert_timetable_documents(
            timetable_documents=timetable_updater.timetables
        )
        log(module_name='look_ahead_handler', log_type='DEBUG',
            log_message='update_timetable_documents (mongodb_database): ok')

    def update_timetables_of_bus_lines(self):
        """
        Update the timetables of all bus_lines, taking into consideration the current levels of traffic_density.

        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            self.update_timetables_of_bus_line(bus_line=bus_line)
class TrafficDataParser(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        self.edge_documents = []
        self.traffic_event_documents = []
        self.minimum_longitude = float("inf")
        self.maximum_longitude = float("-inf")
        self.minimum_latitude = float("inf")
        self.maximum_latitude = float("-inf")
        log(module_name="traffic_data_parser", log_type="DEBUG", log_message="mongodb_database_connection: established")

    def check_borders_of_traffic_event_document(self, traffic_event_document):
        """
        Check if a traffic_event_document corresponds to the operation area, by comparing their borders.
        If yes, then return True. Otherwise, False.

        traffic_event_document: {
            '_id', 'event_id', 'event_type', 'event_level', 'point': {'longitude', 'latitude'}, 'datetime'
        }
        :param traffic_event_document: traffic_event_document
        :return: included_in_borders: bool
        """
        included_in_borders = True
        traffic_event_point_document = traffic_event_document.get("point")
        traffic_event_longitude = traffic_event_point_document.get("longitude")
        traffic_event_latitude = traffic_event_point_document.get("latitude")

        if (
            traffic_event_longitude < self.minimum_longitude
            or traffic_event_longitude > self.maximum_longitude
            or traffic_event_latitude < self.minimum_latitude
            or traffic_event_latitude > self.maximum_latitude
        ):
            included_in_borders = False

        return included_in_borders

    @staticmethod
    def estimate_traffic_density_value(event_level):
        """
        Estimate the traffic_density_value based on the event_level.

        :param event_level: int
        :return: traffic_density_value: float
        """
        if event_level == 1:
            traffic_density_value = 0.2
        elif event_level == 2:
            traffic_density_value = 0.4
        elif event_level == 3:
            traffic_density_value = 0.6
        elif event_level == 4:
            traffic_density_value = 0.8
        else:
            traffic_density_value = 0.0

        return traffic_density_value

    @staticmethod
    def get_edge_document_with_minimum_distance(traffic_event_document, edge_documents):
        """
        Get the edge_document which corresponds to the nearest point of a traffic_event.

        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        traffic_event_document: {
            '_id', 'event_id', 'event_type', 'event_level', 'point': {'longitude', 'latitude'}, 'datetime'
        }
        :param traffic_event_document: traffic_event_document
        :param edge_documents: [edge_document]
        :return:
        """
        edge_document_with_minimum_distance = None
        minimum_distance = float("Inf")

        traffic_event_point_document = traffic_event_document.get("point")
        traffic_event_longitude = traffic_event_point_document.get("longitude")
        traffic_event_latitude = traffic_event_point_document.get("latitude")

        traffic_event_point = Point(longitude=traffic_event_longitude, latitude=traffic_event_latitude)
        for edge_document in edge_documents:
            starting_node = edge_document.get("starting_node")
            starting_node_point_document = starting_node.get("point")
            starting_node_point = Point(
                longitude=starting_node_point_document.get("longitude"),
                latitude=starting_node_point_document.get("latitude"),
            )
            ending_node = edge_document.get("ending_node")
            ending_node_point_document = ending_node.get("point")
            ending_node_point = Point(
                longitude=ending_node_point_document.get("longitude"),
                latitude=ending_node_point_document.get("latitude"),
            )
            distance_of_starting_node = distance(point_one=traffic_event_point, point_two=starting_node_point)
            distance_of_ending_node = distance(point_one=traffic_event_point, point_two=ending_node_point)
            distance_of_edge_document = distance_of_starting_node + distance_of_ending_node

            if distance_of_edge_document < minimum_distance:
                edge_document_with_minimum_distance = edge_document
                minimum_distance = distance_of_edge_document

        return edge_document_with_minimum_distance

    def set_borders_of_operation_area(self, edge_documents):
        """
        Set the minimum and maximum values for longitude and latitude of the operation area.

        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        :param edge_documents: [edge_document]
        :return: None
        """
        for edge_document in edge_documents:
            starting_node = edge_document.get("starting_node")
            starting_node_point_document = starting_node.get("point")
            starting_node_longitude = starting_node_point_document.get("longitude")
            starting_node_latitude = starting_node_point_document.get("latitude")

            if starting_node_longitude < self.minimum_longitude:
                self.minimum_longitude = starting_node_longitude

            if starting_node_longitude > self.maximum_longitude:
                self.maximum_longitude = starting_node_longitude

            if starting_node_latitude < self.minimum_latitude:
                self.minimum_latitude = starting_node_latitude

            if starting_node_latitude > self.maximum_latitude:
                self.maximum_latitude = starting_node_latitude

            ending_node = edge_document.get("ending_node")
            ending_node_point_document = ending_node.get("point")
            ending_node_longitude = ending_node_point_document.get("longitude")
            ending_node_latitude = ending_node_point_document.get("latitude")

            if ending_node_longitude < self.minimum_longitude:
                self.minimum_longitude = ending_node_longitude

            if ending_node_longitude > self.maximum_longitude:
                self.maximum_longitude = ending_node_longitude

            if ending_node_latitude < self.minimum_latitude:
                self.minimum_latitude = ending_node_latitude

            if ending_node_latitude > self.maximum_latitude:
                self.maximum_latitude = ending_node_latitude

    def update_traffic_data(self):
        """
        edge_document: {
            '_id', 'starting_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'ending_node': {'osm_id', 'point': {'longitude', 'latitude'}},
            'max_speed', 'road_type', 'way_id', 'traffic_density'
        }
        traffic_event_document: {
            '_id', 'event_id', 'event_type', 'event_level', 'point': {'longitude', 'latitude'}, 'datetime'
        }
        :return: None
        """
        self.edge_documents = self.mongodb_database_connection.find_edge_documents()
        self.traffic_event_documents = self.mongodb_database_connection.find_traffic_event_documents()
        self.set_borders_of_operation_area(edge_documents=self.edge_documents)

        for traffic_event_document in self.traffic_event_documents:

            if self.check_borders_of_traffic_event_document(traffic_event_document=traffic_event_document):
                edge_document_with_minimum_distance = self.get_edge_document_with_minimum_distance(
                    traffic_event_document=traffic_event_document, edge_documents=self.edge_documents
                )
                traffic_density_value = self.estimate_traffic_density_value(
                    event_level=traffic_event_document.get("event_level")
                )
                self.mongodb_database_connection.update_traffic_density(
                    edge_object_id=edge_document_with_minimum_distance.get("_id"),
                    new_traffic_density_value=traffic_density_value,
                )
            else:
                print "traffic_event_document: out_of_borders -", traffic_event_document
class TravelRequestsSimulator(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(host=mongodb_host, port=mongodb_port)
        log(module_name='travel_requests_simulator', log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def clear_travel_requests_collection(self):
        """
        Clear all the documents of the TravelRequests collection.

        :return: None
        """
        self.mongodb_database_connection.clear_travel_request_documents_collection()
        log(module_name='travel_requests_simulator', log_type='DEBUG',
            log_message='clear_travel_request_documents_collection: ok')

    def delete_travel_request_documents(self, object_ids=None, client_ids=None, bus_line_ids=None,
                                        min_departure_datetime=None, max_departure_datetime=None):
        """
        Delete multiple travel_request_documents.

        :param object_ids: [ObjectId]
        :param client_ids: [int]
        :param bus_line_ids: [int]
        :param min_departure_datetime: datetime
        :param max_departure_datetime
        :return: None
        """
        self.mongodb_database_connection.delete_travel_request_documents(
            object_ids=object_ids,
            client_ids=client_ids,
            bus_line_ids=bus_line_ids,
            min_departure_datetime=min_departure_datetime,
            max_departure_datetime=max_departure_datetime
        )
        log(module_name='travel_requests_simulator', log_type='DEBUG',
            log_message='delete_travel_request_documents: ok')

    def generate_random_travel_request_documents(self, initial_datetime, min_number_of_travel_request_documents,
                                                 max_number_of_travel_request_documents):
        """
        Generate random number of travel_request_documents for each bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        :param initial_datetime: datetime
        :param min_number_of_travel_request_documents: int
        :param max_number_of_travel_request_documents: int
        :return: None
        """
        bus_lines = self.mongodb_database_connection.find_bus_line_documents()

        for bus_line in bus_lines:
            number_of_travel_request_documents = random.randint(
                min_number_of_travel_request_documents,
                max_number_of_travel_request_documents
            )
            self.generate_travel_request_documents(
                initial_datetime=initial_datetime,
                number_of_travel_request_documents=number_of_travel_request_documents,
                bus_line=bus_line
            )

    def generate_travel_request_documents(self, initial_datetime, number_of_travel_request_documents,
                                          bus_line=None, bus_line_id=None):
        """
        Generate a specific number of travel_request_documents, for the selected bus_line,
        for a 24hour period starting from a selected datetime, and store them at the
        corresponding collection of the System Database.

        :param initial_datetime: datetime
        :param number_of_travel_request_documents: int
        :param bus_line: bus_line_document
        :param bus_line_id: int
        :return: None
        """
        # 1: The inputs: initial_datetime, number_of_travel_request_documents, and (bus_line or bus_line_id)
        #    are provided to the Travel Requests Simulator, so as a specific number of travel_request_documents
        #    to be generated, for the selected bus_line, for a 24hour period starting from
        #    the selected datetime.
        #
        # 2: If the provided bus_line is None, then the Travel Requests Simulator retrieves from the System Database
        #    the bus_line which corresponds to the provided bus_line_id.
        #
        if bus_line is None and bus_line_id is None:
            return None
        elif bus_line is None:
            bus_line = self.mongodb_database_connection.find_bus_line_document(bus_line_id=bus_line_id)
        else:
            pass

        bus_stops = bus_line.get('bus_stops')
        number_of_bus_stops = len(bus_stops)

        # 3: The Travel Requests Simulator generates the travel_request_documents, taking into consideration
        #    the variation of transportation demand during the hours of the day.
        #
        # distribution_weighted_datetimes = [
        #     (initial_datetime + timedelta(hours=0), 1),
        #     (initial_datetime + timedelta(hours=1), 1),
        #     (initial_datetime + timedelta(hours=2), 1),
        #     (initial_datetime + timedelta(hours=3), 1),
        #     (initial_datetime + timedelta(hours=4), 1),
        #     (initial_datetime + timedelta(hours=5), 1),
        #     (initial_datetime + timedelta(hours=6), 1),
        #     (initial_datetime + timedelta(hours=7), 1),
        #     (initial_datetime + timedelta(hours=8), 1),
        #     (initial_datetime + timedelta(hours=9), 1),
        #     (initial_datetime + timedelta(hours=10), 1),
        #     (initial_datetime + timedelta(hours=11), 1),
        #     (initial_datetime + timedelta(hours=12), 1),
        #     (initial_datetime + timedelta(hours=13), 1),
        #     (initial_datetime + timedelta(hours=14), 1),
        #     (initial_datetime + timedelta(hours=15), 1),
        #     (initial_datetime + timedelta(hours=16), 1),
        #     (initial_datetime + timedelta(hours=17), 1),
        #     (initial_datetime + timedelta(hours=18), 1),
        #     (initial_datetime + timedelta(hours=19), 1),
        #     (initial_datetime + timedelta(hours=20), 1),
        #     (initial_datetime + timedelta(hours=21), 1),
        #     (initial_datetime + timedelta(hours=22), 1),
        #     (initial_datetime + timedelta(hours=23), 1)
        # ]
        distribution_weighted_datetimes = [
            (initial_datetime + timedelta(hours=i),
             travel_requests_simulator_datetime_distribution_weights[i]) for i in range(0, 24)
        ]
        datetime_population = [val for val, cnt in distribution_weighted_datetimes for i in range(cnt)]
        travel_request_documents = []
        maximum_client_id = self.mongodb_database_connection.get_maximum_or_minimum(collection='travel_request')

        for i in range(0, number_of_travel_request_documents):
            client_id = maximum_client_id + 1
            maximum_client_id = client_id
            starting_bus_stop_index = random.randint(0, number_of_bus_stops - 2)
            starting_bus_stop = bus_stops[starting_bus_stop_index]
            ending_bus_stop_index = random.randint(starting_bus_stop_index + 1, number_of_bus_stops - 1)
            ending_bus_stop = bus_stops[ending_bus_stop_index]
            additional_departure_time_interval = random.randint(0, 59)
            departure_datetime = (random.choice(datetime_population) +
                                  timedelta(minutes=additional_departure_time_interval))

            travel_request_document = {
                'client_id': client_id,
                'bus_line_id': bus_line_id,
                'starting_bus_stop': starting_bus_stop,
                'ending_bus_stop': ending_bus_stop,
                'departure_datetime': departure_datetime,
                'arrival_datetime': None,
                'starting_timetable_entry_index': None,
                'ending_timetable_entry_index': None
            }
            travel_request_documents.append(travel_request_document)

        # 4: The generated travel_request_documents are stored at the
        #    TravelRequests collection of the System Database.
        #
        self.mongodb_database_connection.insert_travel_request_documents(
            travel_request_documents=travel_request_documents
        )
Ejemplo n.º 26
0
class TrafficDataParser(object):
    def __init__(self):
        self.mongodb_database_connection = MongodbDatabaseConnection(
            host=mongodb_host, port=mongodb_port)
        self.edge_documents = []
        self.traffic_event_documents = []
        self.minimum_latitude = float('inf')
        self.maximum_latitude = float('-inf')
        self.minimum_longitude = float('inf')
        self.maximum_longitude = float('-inf')
        log(module_name='traffic_data_parser',
            log_type='DEBUG',
            log_message='mongodb_database_connection: established')

    def check_borders_of_traffic_event_document(self, traffic_event_document):
        """
        Check if a traffic_event_document corresponds to the operation area, by comparing their borders.
        If yes, then return True. Otherwise, False.

        :param traffic_event_document: traffic_event_document
        :return: included_in_borders: bool
        """
        included_in_borders = True
        traffic_event_point_document = traffic_event_document.get('point')
        traffic_event_longitude = traffic_event_point_document.get('longitude')
        traffic_event_latitude = traffic_event_point_document.get('latitude')

        if (traffic_event_longitude < self.minimum_longitude
                or traffic_event_longitude > self.maximum_longitude
                or traffic_event_latitude < self.minimum_latitude
                or traffic_event_latitude > self.maximum_latitude):
            included_in_borders = False

        return included_in_borders

    @staticmethod
    def estimate_traffic_density_value(event_level):
        """
        Estimate the traffic_density_value based on the event_level.

        :param event_level: int
        :return: traffic_density_value: float
        """
        if event_level == 1:
            traffic_density_value = 0.2
        elif event_level == 2:
            traffic_density_value = 0.4
        elif event_level == 3:
            traffic_density_value = 0.6
        elif event_level == 4:
            traffic_density_value = 0.8
        else:
            traffic_density_value = 0.0

        return traffic_density_value

    def get_borders_of_operation_area(self):
        """
        Get the minimum and maximum values for longitude and latitude of the operation area.

        :return: borders: {'minimum_latitude', 'maximum_latitude', 'minimum_longitude', 'maximum_longitude'}
        """
        if len(self.edge_documents) == 0:
            self.retrieve_edge_documents()

        self.set_borders_of_operation_area()

        borders = {
            'minimum_latitude': self.minimum_latitude,
            'maximum_latitude': self.maximum_latitude,
            'minimum_longitude': self.minimum_longitude,
            'maximum_longitude': self.maximum_longitude
        }
        return borders

    @staticmethod
    def get_edge_document_with_minimum_distance(traffic_event_document,
                                                edge_documents):
        """
        Get the edge_document which corresponds to the nearest point of a traffic_event.

        :param traffic_event_document: traffic_event_document
        :param edge_documents: [edge_document]
        :return:
        """
        edge_document_with_minimum_distance = None
        minimum_distance = float('Inf')

        traffic_event_point_document = traffic_event_document.get('point')
        traffic_event_longitude = traffic_event_point_document.get('longitude')
        traffic_event_latitude = traffic_event_point_document.get('latitude')

        traffic_event_point = Point(longitude=traffic_event_longitude,
                                    latitude=traffic_event_latitude)
        for edge_document in edge_documents:
            starting_node = edge_document.get('starting_node')
            starting_node_point_document = starting_node.get('point')
            starting_node_point = Point(
                longitude=starting_node_point_document.get('longitude'),
                latitude=starting_node_point_document.get('latitude'))
            ending_node = edge_document.get('ending_node')
            ending_node_point_document = ending_node.get('point')
            ending_node_point = Point(
                longitude=ending_node_point_document.get('longitude'),
                latitude=ending_node_point_document.get('latitude'))
            distance_of_starting_node = distance(point_one=traffic_event_point,
                                                 point_two=starting_node_point)
            distance_of_ending_node = distance(point_one=traffic_event_point,
                                               point_two=ending_node_point)
            distance_of_edge_document = distance_of_starting_node + distance_of_ending_node

            if distance_of_edge_document < minimum_distance:
                edge_document_with_minimum_distance = edge_document
                minimum_distance = distance_of_edge_document

        return edge_document_with_minimum_distance

    def retrieve_edge_documents(self):
        self.edge_documents = self.mongodb_database_connection.find_edge_documents(
        )

    def retrieve_traffic_event_documents(self):
        self.traffic_event_documents = self.mongodb_database_connection.find_traffic_event_documents(
        )

    def set_borders_of_operation_area(self):
        """
        Set the minimum and maximum values for longitude and latitude of the operation area.

        :return: None
        """
        for edge_document in self.edge_documents:
            starting_node = edge_document.get('starting_node')
            starting_node_point_document = starting_node.get('point')
            starting_node_longitude = starting_node_point_document.get(
                'longitude')
            starting_node_latitude = starting_node_point_document.get(
                'latitude')

            if starting_node_longitude < self.minimum_longitude:
                self.minimum_longitude = starting_node_longitude

            if starting_node_longitude > self.maximum_longitude:
                self.maximum_longitude = starting_node_longitude

            if starting_node_latitude < self.minimum_latitude:
                self.minimum_latitude = starting_node_latitude

            if starting_node_latitude > self.maximum_latitude:
                self.maximum_latitude = starting_node_latitude

            ending_node = edge_document.get('ending_node')
            ending_node_point_document = ending_node.get('point')
            ending_node_longitude = ending_node_point_document.get('longitude')
            ending_node_latitude = ending_node_point_document.get('latitude')

            if ending_node_longitude < self.minimum_longitude:
                self.minimum_longitude = ending_node_longitude

            if ending_node_longitude > self.maximum_longitude:
                self.maximum_longitude = ending_node_longitude

            if ending_node_latitude < self.minimum_latitude:
                self.minimum_latitude = ending_node_latitude

            if ending_node_latitude > self.maximum_latitude:
                self.maximum_latitude = ending_node_latitude

    def update_traffic_data(self):
        """

        :return: None
        """
        self.retrieve_edge_documents()
        self.retrieve_traffic_event_documents()
        self.set_borders_of_operation_area()

        for traffic_event_document in self.traffic_event_documents:

            if self.check_borders_of_traffic_event_document(
                    traffic_event_document=traffic_event_document):
                edge_document_with_minimum_distance = self.get_edge_document_with_minimum_distance(
                    traffic_event_document=traffic_event_document,
                    edge_documents=self.edge_documents)
                traffic_density_value = self.estimate_traffic_density_value(
                    event_level=traffic_event_document.get('event_level'))
                self.mongodb_database_connection.update_traffic_density(
                    edge_object_id=edge_document_with_minimum_distance.get(
                        '_id'),
                    new_traffic_density_value=traffic_density_value)
            else:
                print 'traffic_event_document: out_of_borders -', traffic_event_document