#ifndef OSRM_GUIDANCE_STATISTICS_HANDLER_HPP_ #define OSRM_GUIDANCE_STATISTICS_HANDLER_HPP_ #include "guidance/intersection.hpp" #include "guidance/intersection_handler.hpp" #include "guidance/turn_instruction.hpp" #include "util/log.hpp" #include #include #include #include #include #include namespace osrm { namespace guidance { // Unconditionally runs over all intersections and gathers statistics for // instruction turn types and direction modifiers (see turn_instruction.hpp). class StatisticsHandler final : public IntersectionHandler { public: StatisticsHandler(const util::NodeBasedDynamicGraph &node_based_graph, const extractor::EdgeBasedNodeDataContainer &node_data_container, const std::vector &coordinates, const extractor::CompressedEdgeContainer &compressed_geometries, const extractor::RestrictionMap &node_restriction_map, const std::unordered_set &barrier_nodes, const extractor::TurnLanesIndexedArray &turn_lanes_data, const extractor::NameTable &name_table, const extractor::SuffixTable &street_name_suffix_table) : IntersectionHandler(node_based_graph, node_data_container, coordinates, compressed_geometries, node_restriction_map, barrier_nodes, turn_lanes_data, name_table, street_name_suffix_table) { } ~StatisticsHandler() override final { const auto add_second = [](const auto acc, const auto &kv) { return acc + kv.second; }; const auto num_types = std::accumulate(begin(type_hist), end(type_hist), std::uint64_t{0}, add_second); const auto num_modifiers = std::accumulate(begin(modifier_hist), end(modifier_hist), std::uint64_t{0}, add_second); util::Log() << "Assigned " << num_types << " turn instruction types:"; for (const auto &kv : type_hist) if (kv.second > 0) util::Log() << " " << std::fixed << std::setprecision(2) << internalInstructionTypeToString(kv.first) << ": " << kv.second << " (" << (kv.second / static_cast(num_types) * 100.) << "%)"; util::Log() << "Assigned " << num_modifiers << " turn instruction modifiers:"; for (const auto &kv : modifier_hist) if (kv.second > 0) util::Log() << " " << std::fixed << std::setprecision(2) << instructionModifierToString(kv.first) << ": " << kv.second << " (" << (kv.second / static_cast(num_modifiers) * 100.) << "%)"; } bool canProcess(const NodeID, const EdgeID, const Intersection &) const override final { return true; } Intersection operator()(const NodeID, const EdgeID, Intersection intersection) const override final { // Lock histograms updates on a per-intersection basis. std::lock_guard defer{lock}; // Generate histograms for all roads; this way we will get duplicates // which we would not get doing it after EBF generation. But we want // numbers closer to the handlers and see how often handlers ran. for (const auto &road : intersection) { if (road.entry_allowed) { const auto type = road.instruction.type; const auto modifier = road.instruction.direction_modifier; type_hist[type] += 1; modifier_hist[modifier] += 1; } } return intersection; } private: mutable std::mutex lock; mutable std::map type_hist; mutable std::map modifier_hist; }; } // namespace guidance } // namespace osrm #endif // OSRM_GUIDANCE_VALIDATION_HANDLER_HPP_