diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 6977c779ae3..b9b3a49b33b 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -41,6 +41,7 @@ class MatchAPI final : public RouteAPI sub_routes[index].source_traversed_in_reverse, sub_routes[index].target_traversed_in_reverse); route.values["confidence"] = sub_matchings[index].confidence; + routes.values.push_back(std::move(route)); } response.values["tracepoints"] = MakeTracepoints(sub_matchings); response.values["routes"] = std::move(routes); diff --git a/include/engine/api/match_parameters.hpp b/include/engine/api/match_parameters.hpp index 66647abf111..884157d3d95 100644 --- a/include/engine/api/match_parameters.hpp +++ b/include/engine/api/match_parameters.hpp @@ -14,6 +14,18 @@ namespace api struct MatchParameters : public RouteParameters { + MatchParameters() + : RouteParameters(false, false, RouteParameters::GeometriesType::Polyline, RouteParameters::OverviewType::Simplified, {}) + { + } + + template + MatchParameters(std::vector timestamps_, + Args... args_) + : RouteParameters{std::forward(args_)...}, timestamps{std::move(timestamps_)} + { + } + std::vector timestamps; bool IsValid() const { diff --git a/include/server/api/match_parameter_grammar.hpp b/include/server/api/match_parameter_grammar.hpp index 17af73bcc1a..3c377a2bb65 100644 --- a/include/server/api/match_parameter_grammar.hpp +++ b/include/server/api/match_parameter_grammar.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -23,16 +24,61 @@ namespace qi = boost::spirit::qi; struct MatchParametersGrammar final : public BaseParametersGrammar { using Iterator = std::string::iterator; + using StepsT = bool; + using TimestampsT = std::vector; + using GeometriesT = engine::api::RouteParameters::GeometriesType; + using OverviewT = engine::api::RouteParameters::OverviewType; MatchParametersGrammar() : BaseParametersGrammar(root_rule, parameters) { - root_rule = "TODO(daniel-j-h)"; + const auto set_geojson_type = [this]() + { + parameters.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; + }; + const auto set_polyline_type = [this]() + { + parameters.geometries = engine::api::RouteParameters::GeometriesType::Polyline; + }; + + const auto set_simplified_type = [this]() + { + parameters.overview = engine::api::RouteParameters::OverviewType::Simplified; + }; + const auto set_full_type = [this]() + { + parameters.overview = engine::api::RouteParameters::OverviewType::Full; + }; + const auto set_false_type = [this]() + { + parameters.overview = engine::api::RouteParameters::OverviewType::False; + }; + const auto set_steps = [this](const StepsT steps) + { + parameters.steps = steps; + }; + const auto set_timestamps = [this](TimestampsT ×tamps) + { + parameters.timestamps = std::move(timestamps); + }; + + steps_rule = qi::lit("steps=") >> qi::bool_; + geometries_rule = qi::lit("geometries=geojson")[set_geojson_type] | + qi::lit("geometries=polyline")[set_polyline_type]; + overview_rule = qi::lit("overview=simplified")[set_simplified_type] | + qi::lit("overview=full")[set_full_type] | + qi::lit("overview=false")[set_false_type]; + timestamps_rule = qi::lit("timestamps=") >> qi::uint_ % ";"; + match_rule = steps_rule[set_steps] | geometries_rule | + overview_rule | timestamps_rule[set_timestamps]; + root_rule = -((base_rule | match_rule) % '&'); } engine::api::MatchParameters parameters; private: - qi::rule root_rule, match_rule; + qi::rule root_rule, match_rule, geometries_rule, overview_rule; + qi::rule timestamps_rule; + qi::rule steps_rule; }; } } diff --git a/include/server/service/utils.hpp b/include/server/service/utils.hpp new file mode 100644 index 00000000000..6d57438bb2d --- /dev/null +++ b/include/server/service/utils.hpp @@ -0,0 +1,31 @@ +#include + +namespace osrm +{ +namespace server +{ +namespace service +{ + +const constexpr char PARAMETER_SIZE_MISMATCH_MSG[] = + "Number of elements in %1% size %2% does not match coordinate size %3%"; + +template +bool constrainParamSize(const char *msg_template, + const char *name, + const ParamT ¶m, + const std::size_t target_size, + std::string &help) +{ + if (param.size() > 0 && param.size() != target_size) + { + help = (boost::format(msg_template) % name % param.size() % target_size).str(); + return true; + } + return false; +} + +} +} +} + diff --git a/src/server/service/match_service.cpp b/src/server/service/match_service.cpp index ee616f2181c..2f519fc2ebe 100644 --- a/src/server/service/match_service.cpp +++ b/src/server/service/match_service.cpp @@ -2,6 +2,7 @@ #include "engine/api/match_parameters.hpp" #include "server/api/parameters_parser.hpp" +#include "server/service/utils.hpp" #include "util/json_container.hpp" @@ -13,13 +14,60 @@ namespace server { namespace service { +namespace +{ +std::string getWrongOptionHelp(const engine::api::MatchParameters ¶meters) +{ + std::string help; + + const auto coord_size = parameters.coordinates.size(); + + const bool param_size_mismatch = constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "hints", + parameters.hints, coord_size, help) || + constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "bearings", + parameters.bearings, coord_size, help) || + constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "radiuses", + parameters.radiuses, coord_size, help) || + constrainParamSize(PARAMETER_SIZE_MISMATCH_MSG, "timestamps", + parameters.timestamps, coord_size, help); + + if (!param_size_mismatch && parameters.coordinates.size() < 2) + { + help = "Number of coordinates needs to be at least two."; + } + + return help; +} +} // anon. ns engine::Status MatchService::RunQuery(std::vector coordinates, std::string &options, util::json::Object &result) { - // TODO(daniel-j-h) - return Status::Error; + auto options_iterator = options.begin(); + auto parameters = + api::parseParameters(options_iterator, options.end()); + if (!parameters || options_iterator != options.end()) + { + const auto position = std::distance(options.begin(), options_iterator); + result.values["code"] = "invalid-options"; + result.values["message"] = + "Options string malformed close to position " + std::to_string(position); + return engine::Status::Error; + } + + BOOST_ASSERT(parameters); + parameters->coordinates = std::move(coordinates); + + if (!parameters->IsValid()) + { + result.values["code"] = "invalid-options"; + result.values["message"] = getWrongOptionHelp(*parameters); + return engine::Status::Error; + } + BOOST_ASSERT(parameters->IsValid()); + + return BaseService::routing_machine.Match(*parameters, result); } } } diff --git a/src/server/service/route_service.cpp b/src/server/service/route_service.cpp index 4dffcf026ed..a715662d646 100644 --- a/src/server/service/route_service.cpp +++ b/src/server/service/route_service.cpp @@ -1,40 +1,19 @@ #include "server/service/route_service.hpp" +#include "server/service/utils.hpp" #include "engine/api/route_parameters.hpp" #include "server/api/parameters_parser.hpp" #include "util/json_container.hpp" -#include - namespace osrm { namespace server { namespace service { - namespace { - -const constexpr char PARAMETER_SIZE_MISMATCH_MSG[] = - "Number of elements in %1% size %2% does not match coordinate size %3%"; - -template -bool constrainParamSize(const char *msg_template, - const char *name, - const ParamT ¶m, - const std::size_t target_size, - std::string &help) -{ - if (param.size() > 0 && param.size() != target_size) - { - help = (boost::format(msg_template) % name % param.size() % target_size).str(); - return true; - } - return false; -} - std::string getWrongOptionHelp(const engine::api::RouteParameters ¶meters) { std::string help; @@ -63,7 +42,6 @@ engine::Status RouteService::RunQuery(std::vector co std::string &options, util::json::Object &result) { - auto options_iterator = options.begin(); auto parameters = api::parseParameters(options_iterator, options.end());