osrm-backend/include/guidance/statistics_handler.hpp
2022-12-20 18:00:11 +01:00

111 lines
4.1 KiB
C++

#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 <algorithm>
#include <iomanip>
#include <iterator>
#include <map>
#include <mutex>
#include <cstdint>
namespace osrm::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<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
const std::unordered_set<NodeID> &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<float>(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<float>(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<std::mutex> 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<TurnType::Enum, std::uint64_t> type_hist;
mutable std::map<DirectionModifier::Enum, std::uint64_t> modifier_hist;
};
} // namespace osrm::guidance
#endif // OSRM_GUIDANCE_VALIDATION_HANDLER_HPP_