111 lines
4.1 KiB
C++
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_
|