OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright 2015, Google Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are |
| 8 * met: |
| 9 * |
| 10 * * Redistributions of source code must retain the above copyright |
| 11 * notice, this list of conditions and the following disclaimer. |
| 12 * * Redistributions in binary form must reproduce the above |
| 13 * copyright notice, this list of conditions and the following disclaimer |
| 14 * in the documentation and/or other materials provided with the |
| 15 * distribution. |
| 16 * * Neither the name of Google Inc. nor the names of its |
| 17 * contributors may be used to endorse or promote products derived from |
| 18 * this software without specific prior written permission. |
| 19 * |
| 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 * |
| 32 */ |
| 33 |
| 34 #include <algorithm> |
| 35 #include <chrono> |
| 36 #include <cmath> |
| 37 #include <iostream> |
| 38 #include <memory> |
| 39 #include <string> |
| 40 |
| 41 #include <grpc/grpc.h> |
| 42 #include <grpc++/server.h> |
| 43 #include <grpc++/server_builder.h> |
| 44 #include <grpc++/server_context.h> |
| 45 #include <grpc++/security/server_credentials.h> |
| 46 #include "helper.h" |
| 47 #include "route_guide.grpc.pb.h" |
| 48 |
| 49 using grpc::Server; |
| 50 using grpc::ServerBuilder; |
| 51 using grpc::ServerContext; |
| 52 using grpc::ServerReader; |
| 53 using grpc::ServerReaderWriter; |
| 54 using grpc::ServerWriter; |
| 55 using grpc::Status; |
| 56 using routeguide::Point; |
| 57 using routeguide::Feature; |
| 58 using routeguide::Rectangle; |
| 59 using routeguide::RouteSummary; |
| 60 using routeguide::RouteNote; |
| 61 using routeguide::RouteGuide; |
| 62 using std::chrono::system_clock; |
| 63 |
| 64 |
| 65 float ConvertToRadians(float num) { |
| 66 return num * 3.1415926 /180; |
| 67 } |
| 68 |
| 69 float GetDistance(const Point& start, const Point& end) { |
| 70 const float kCoordFactor = 10000000.0; |
| 71 float lat_1 = start.latitude() / kCoordFactor; |
| 72 float lat_2 = end.latitude() / kCoordFactor; |
| 73 float lon_1 = start.longitude() / kCoordFactor; |
| 74 float lon_2 = end.longitude() / kCoordFactor; |
| 75 float lat_rad_1 = ConvertToRadians(lat_1); |
| 76 float lat_rad_2 = ConvertToRadians(lat_2); |
| 77 float delta_lat_rad = ConvertToRadians(lat_2-lat_1); |
| 78 float delta_lon_rad = ConvertToRadians(lon_2-lon_1); |
| 79 |
| 80 float a = pow(sin(delta_lat_rad/2), 2) + cos(lat_rad_1) * cos(lat_rad_2) * |
| 81 pow(sin(delta_lon_rad/2), 2); |
| 82 float c = 2 * atan2(sqrt(a), sqrt(1-a)); |
| 83 int R = 6371000; // metres |
| 84 |
| 85 return R * c; |
| 86 } |
| 87 |
| 88 std::string GetFeatureName(const Point& point, |
| 89 const std::vector<Feature>& feature_list) { |
| 90 for (const Feature& f : feature_list) { |
| 91 if (f.location().latitude() == point.latitude() && |
| 92 f.location().longitude() == point.longitude()) { |
| 93 return f.name(); |
| 94 } |
| 95 } |
| 96 return ""; |
| 97 } |
| 98 |
| 99 class RouteGuideImpl final : public RouteGuide::Service { |
| 100 public: |
| 101 explicit RouteGuideImpl(const std::string& db) { |
| 102 routeguide::ParseDb(db, &feature_list_); |
| 103 } |
| 104 |
| 105 Status GetFeature(ServerContext* context, const Point* point, |
| 106 Feature* feature) override { |
| 107 feature->set_name(GetFeatureName(*point, feature_list_)); |
| 108 feature->mutable_location()->CopyFrom(*point); |
| 109 return Status::OK; |
| 110 } |
| 111 |
| 112 Status ListFeatures(ServerContext* context, |
| 113 const routeguide::Rectangle* rectangle, |
| 114 ServerWriter<Feature>* writer) override { |
| 115 auto lo = rectangle->lo(); |
| 116 auto hi = rectangle->hi(); |
| 117 long left = (std::min)(lo.longitude(), hi.longitude()); |
| 118 long right = (std::max)(lo.longitude(), hi.longitude()); |
| 119 long top = (std::max)(lo.latitude(), hi.latitude()); |
| 120 long bottom = (std::min)(lo.latitude(), hi.latitude()); |
| 121 for (const Feature& f : feature_list_) { |
| 122 if (f.location().longitude() >= left && |
| 123 f.location().longitude() <= right && |
| 124 f.location().latitude() >= bottom && |
| 125 f.location().latitude() <= top) { |
| 126 writer->Write(f); |
| 127 } |
| 128 } |
| 129 return Status::OK; |
| 130 } |
| 131 |
| 132 Status RecordRoute(ServerContext* context, ServerReader<Point>* reader, |
| 133 RouteSummary* summary) override { |
| 134 Point point; |
| 135 int point_count = 0; |
| 136 int feature_count = 0; |
| 137 float distance = 0.0; |
| 138 Point previous; |
| 139 |
| 140 system_clock::time_point start_time = system_clock::now(); |
| 141 while (reader->Read(&point)) { |
| 142 point_count++; |
| 143 if (!GetFeatureName(point, feature_list_).empty()) { |
| 144 feature_count++; |
| 145 } |
| 146 if (point_count != 1) { |
| 147 distance += GetDistance(previous, point); |
| 148 } |
| 149 previous = point; |
| 150 } |
| 151 system_clock::time_point end_time = system_clock::now(); |
| 152 summary->set_point_count(point_count); |
| 153 summary->set_feature_count(feature_count); |
| 154 summary->set_distance(static_cast<long>(distance)); |
| 155 auto secs = std::chrono::duration_cast<std::chrono::seconds>( |
| 156 end_time - start_time); |
| 157 summary->set_elapsed_time(secs.count()); |
| 158 |
| 159 return Status::OK; |
| 160 } |
| 161 |
| 162 Status RouteChat(ServerContext* context, |
| 163 ServerReaderWriter<RouteNote, RouteNote>* stream) override { |
| 164 std::vector<RouteNote> received_notes; |
| 165 RouteNote note; |
| 166 while (stream->Read(¬e)) { |
| 167 for (const RouteNote& n : received_notes) { |
| 168 if (n.location().latitude() == note.location().latitude() && |
| 169 n.location().longitude() == note.location().longitude()) { |
| 170 stream->Write(n); |
| 171 } |
| 172 } |
| 173 received_notes.push_back(note); |
| 174 } |
| 175 |
| 176 return Status::OK; |
| 177 } |
| 178 |
| 179 private: |
| 180 |
| 181 std::vector<Feature> feature_list_; |
| 182 }; |
| 183 |
| 184 void RunServer(const std::string& db_path) { |
| 185 std::string server_address("0.0.0.0:50051"); |
| 186 RouteGuideImpl service(db_path); |
| 187 |
| 188 ServerBuilder builder; |
| 189 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); |
| 190 builder.RegisterService(&service); |
| 191 std::unique_ptr<Server> server(builder.BuildAndStart()); |
| 192 std::cout << "Server listening on " << server_address << std::endl; |
| 193 server->Wait(); |
| 194 } |
| 195 |
| 196 int main(int argc, char** argv) { |
| 197 // Expect only arg: --db_path=path/to/route_guide_db.json. |
| 198 std::string db = routeguide::GetDbFileContent(argc, argv); |
| 199 RunServer(db); |
| 200 |
| 201 return 0; |
| 202 } |
OLD | NEW |