• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""The Python implementation of the gRPC route guide server."""
15
16from concurrent import futures
17import time
18import math
19import logging
20
21import grpc
22
23import route_guide_pb2
24import route_guide_pb2_grpc
25import route_guide_resources
26
27
28def get_feature(feature_db, point):
29    """Returns Feature at given location or None."""
30    for feature in feature_db:
31        if feature.location == point:
32            return feature
33    return None
34
35
36def get_distance(start, end):
37    """Distance between two points."""
38    coord_factor = 10000000.0
39    lat_1 = start.latitude / coord_factor
40    lat_2 = end.latitude / coord_factor
41    lon_1 = start.longitude / coord_factor
42    lon_2 = end.longitude / coord_factor
43    lat_rad_1 = math.radians(lat_1)
44    lat_rad_2 = math.radians(lat_2)
45    delta_lat_rad = math.radians(lat_2 - lat_1)
46    delta_lon_rad = math.radians(lon_2 - lon_1)
47
48    # Formula is based on http://mathforum.org/library/drmath/view/51879.html
49    a = (pow(math.sin(delta_lat_rad / 2), 2) +
50         (math.cos(lat_rad_1) * math.cos(lat_rad_2) *
51          pow(math.sin(delta_lon_rad / 2), 2)))
52    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
53    R = 6371000
54    # metres
55    return R * c
56
57
58class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):
59    """Provides methods that implement functionality of route guide server."""
60
61    def __init__(self):
62        self.db = route_guide_resources.read_route_guide_database()
63
64    def GetFeature(self, request, context):
65        feature = get_feature(self.db, request)
66        if feature is None:
67            return route_guide_pb2.Feature(name="", location=request)
68        else:
69            return feature
70
71    def ListFeatures(self, request, context):
72        left = min(request.lo.longitude, request.hi.longitude)
73        right = max(request.lo.longitude, request.hi.longitude)
74        top = max(request.lo.latitude, request.hi.latitude)
75        bottom = min(request.lo.latitude, request.hi.latitude)
76        for feature in self.db:
77            if (feature.location.longitude >= left and
78                    feature.location.longitude <= right and
79                    feature.location.latitude >= bottom and
80                    feature.location.latitude <= top):
81                yield feature
82
83    def RecordRoute(self, request_iterator, context):
84        point_count = 0
85        feature_count = 0
86        distance = 0.0
87        prev_point = None
88
89        start_time = time.time()
90        for point in request_iterator:
91            point_count += 1
92            if get_feature(self.db, point):
93                feature_count += 1
94            if prev_point:
95                distance += get_distance(prev_point, point)
96            prev_point = point
97
98        elapsed_time = time.time() - start_time
99        return route_guide_pb2.RouteSummary(point_count=point_count,
100                                            feature_count=feature_count,
101                                            distance=int(distance),
102                                            elapsed_time=int(elapsed_time))
103
104    def RouteChat(self, request_iterator, context):
105        prev_notes = []
106        for new_note in request_iterator:
107            for prev_note in prev_notes:
108                if prev_note.location == new_note.location:
109                    yield prev_note
110            prev_notes.append(new_note)
111
112
113def serve():
114    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
115    route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
116        RouteGuideServicer(), server)
117    server.add_insecure_port('[::]:50051')
118    server.start()
119    server.wait_for_termination()
120
121
122if __name__ == '__main__':
123    logging.basicConfig()
124    serve()
125