diff --git a/cpp/route_guide/route_guide_client.cc b/cpp/route_guide/route_guide_client.cc index 86f603f5b47..8b4a5323271 100644 --- a/cpp/route_guide/route_guide_client.cc +++ b/cpp/route_guide/route_guide_client.cc @@ -90,6 +90,19 @@ bool ParseDb(const std::string& stream, std::vector* feature_list) { // TODO } +void FillFeatureList(const std::string& db_path, std::vector* feature_list) { + if (db_path.empty()) { + return; + } + std::ifstream db_file(db_path); + if (!db_file.is_open()) { + std::cout << "Failed to open " << db_path << std::endl; + } + std::stringstream db; + db << db_file.rdbuf(); + ParseDb(db.str(), feature_list); +} + class RouteGuideClient { public: RouteGuideClient(std::shared_ptr channel) @@ -207,16 +220,7 @@ class RouteGuideClient { void Shutdown() { stub_.reset(); } void FillFeatureList(const std::string& db_path) { - if (db_path.empty()) { - return; - } - std::ifstream db_file(db_path); - if (!db_file.is_open()) { - std::cout << "Failed to open " << db_path << std::endl; - } - std::stringstream db; - db << db_file.rdbuf(); - ParseDb(db.str(), &feature_list_); + ::FillFeatureList(db_path, &feature_list_); } private: diff --git a/cpp/route_guide/route_guide_server.cc b/cpp/route_guide/route_guide_server.cc index 718afbae2a8..d4ecded69ba 100644 --- a/cpp/route_guide/route_guide_server.cc +++ b/cpp/route_guide/route_guide_server.cc @@ -31,8 +31,13 @@ * */ +#include +#include +#include +#include #include #include +#include #include #include @@ -57,29 +62,148 @@ using examples::Rectangle; using examples::RouteSummary; using examples::RouteNote; using examples::RouteGuide; +using std::chrono::system_clock; + +const float kCoordFactor = 10000000.0; + +bool ParseDb(const std::string& stream, std::vector* feature_list) { + // TODO +} + +float ConvertToRadians(float num) { + return num * 3.1415926 /180; +} + +float GetDistance(const Point& start, const Point& end) { + + float lat_1 = start.latitude() / kCoordFactor; + float lat_2 = end.latitude() / kCoordFactor; + float lon_1 = start.longitude() / kCoordFactor; + float lon_2 = end.longitude() / kCoordFactor; + float lat_rad_1 = ConvertToRadians(lat_1); + float lat_rad_2 = ConvertToRadians(lat_2); + float delta_lat_rad = ConvertToRadians(lat_2-lat_1); + float delta_lon_rad = ConvertToRadians(lon_2-lon_1); + + float a = pow(sin(delta_lat_rad/2), 2) + cos(lat_rad_1) * cos(lat_rad_2) * + pow(sin(delta_lon_rad/2), 2); + float c = 2 * atan2(sqrt(a), sqrt(1-a)); + int R = 6371000; // metres + + return R * c; +} + +void FillFeatureList(const std::string& db_path, std::vector* feature_list) { + if (db_path.empty()) { + return; + } + std::ifstream db_file(db_path); + if (!db_file.is_open()) { + std::cout << "Failed to open " << db_path << std::endl; + } + std::stringstream db; + db << db_file.rdbuf(); + ParseDb(db.str(), feature_list); +} + +std::string GetFeatureName(const Point& point, + const std::vector& feature_list) { + for (const Feature& f : feature_list) { + if (f.location().latitude() == point.latitude() && + f.location().longitude() == point.longitude()) { + return f.name(); + } + } + return ""; +} class RouteGuideImpl final : public RouteGuide::Service { + public: + RouteGuideImpl(const std::string& db_path) { + FillFeatureList(db_path, &feature_list_); + } + Status GetFeature(ServerContext* context, const Point* point, Feature* feature) override { + feature->set_name(GetFeatureName(*point, feature_list_)); + feature->mutable_location()->CopyFrom(*point); return Status::OK; } + Status ListFeatures(ServerContext* context, const Rectangle* rectangle, ServerWriter* writer) override { + auto lo = rectangle->lo(); + auto hi = rectangle->hi(); + long left = std::min(lo.longitude(), hi.longitude()); + long right = std::max(lo.longitude(), hi.longitude()); + long top = std::max(lo.latitude(), hi.latitude()); + long bottom = std::min(lo.latitude(), hi.latitude()); + for (const Feature& f : feature_list_) { + if (f.location().longitude() >= left && + f.location().longitude() <= right && + f.location().latitude() >= bottom && + f.location().latitude() <= top) { + writer->Write(f); + } + } return Status::OK; } + Status RecordRoute(ServerContext* context, ServerReader* reader, RouteSummary* summary) override { + Point point; + int point_count = 0; + int feature_count = 0; + float distance = 0.0; + Point previous; + + system_clock::time_point start_time = system_clock::now(); + while (reader->Read(&point)) { + point_count++; + if (!GetFeatureName(point, feature_list_).empty()) { + feature_count++; + } + if (point_count != 1) { + distance += GetDistance(previous, point); + } + previous = point; + } + system_clock::time_point end_time = system_clock::now(); + summary->set_point_count(point_count); + summary->set_feature_count(feature_count); + summary->set_distance(static_cast(distance)); + auto secs = std::chrono::duration_cast( + end_time - start_time); + summary->set_elapsed_time(secs.count()); + return Status::OK; } + Status RouteChat(ServerContext* context, ServerReaderWriter* stream) override { + std::vector received_notes; + RouteNote note; + while (stream->Read(¬e)) { + for (const RouteNote& n : received_notes) { + if (n.location().latitude() == note.location().latitude() && + n.location().longitude() == note.location().longitude()) { + stream->Write(n); + } + } + received_notes.push_back(note); + } + return Status::OK; } + + private: + + std::vector feature_list_; }; -void RunServer() { +void RunServer(const std::string& db_path) { std::string server_address("0.0.0.0:50051"); - RouteGuideImpl service; + RouteGuideImpl service(db_path); ServerBuilder builder; builder.AddPort(server_address); @@ -94,7 +218,20 @@ void RunServer() { int main(int argc, char** argv) { grpc_init(); - RunServer(); + std::string db_path; + std::string arg_str("--db_path"); + if (argc > 1) { + std::string argv_1 = argv[1]; + size_t start_position = argv_1.find(arg_str); + if (start_position != std::string::npos) { + start_position += arg_str.size(); + if (argv_1[start_position] == ' ' || + argv_1[start_position] == '=') { + db_path = argv_1.substr(start_position + 1); + } + } + } + RunServer(db_path); grpc_shutdown(); return 0;