Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
282
tools/openlr/openlr_stat/openlr_stat.cpp
Normal file
282
tools/openlr/openlr_stat/openlr_stat.cpp
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
#include "openlr/openlr_decoder.hpp"
|
||||
|
||||
#include "routing/road_graph.hpp"
|
||||
|
||||
#include "indexer/classificator_loader.hpp"
|
||||
#include "indexer/data_source.hpp"
|
||||
|
||||
#include "storage/country_parent_getter.hpp"
|
||||
|
||||
#include "platform/local_country_file.hpp"
|
||||
#include "platform/local_country_file_utils.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
|
||||
#include "openlr/decoded_path.hpp"
|
||||
#include "openlr/openlr_model.hpp"
|
||||
#include "openlr/openlr_model_xml.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <clocale>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <pugixml.hpp>
|
||||
|
||||
DEFINE_string(input, "", "Path to OpenLR file.");
|
||||
DEFINE_string(spark_output, "", "Path to output file in spark-oriented format");
|
||||
DEFINE_string(assessment_output, "", "Path to output file in assessment-tool oriented format");
|
||||
|
||||
DEFINE_string(non_matched_ids, "non-matched-ids.txt", "Path to a file ids of non-matched segments will be saved to");
|
||||
DEFINE_string(mwms_path, "", "Path to a folder with mwms.");
|
||||
DEFINE_string(resources_path, "", "Path to a folder with resources.");
|
||||
DEFINE_int32(limit, -1, "Max number of segments to handle. -1 for all.");
|
||||
DEFINE_bool(multipoints_only, false, "Only segments with multiple points to handle.");
|
||||
DEFINE_int32(num_threads, 1, "Number of threads.");
|
||||
DEFINE_string(ids_path, "", "Path to a file with segment ids to process.");
|
||||
DEFINE_string(countries_filename, "",
|
||||
"Name of countries file which describes mwm tree. Used to get country specific "
|
||||
"routing restrictions.");
|
||||
DEFINE_int32(algo_version, 0, "Use new decoding algorithm");
|
||||
|
||||
using namespace openlr;
|
||||
|
||||
namespace
|
||||
{
|
||||
int32_t const kMinNumThreads = 1;
|
||||
int32_t const kMaxNumThreads = 128;
|
||||
int32_t const kHandleAllSegments = -1;
|
||||
|
||||
void LoadDataSources(std::string const & pathToMWMFolder, std::vector<FrozenDataSource> & dataSources)
|
||||
{
|
||||
CHECK(Platform::IsDirectory(pathToMWMFolder), (pathToMWMFolder, "must be a directory."));
|
||||
|
||||
Platform::FilesList files;
|
||||
Platform::GetFilesByRegExp(pathToMWMFolder, boost::regex(".*\\") + DATA_FILE_EXTENSION, files);
|
||||
|
||||
CHECK(!files.empty(), (pathToMWMFolder, "Contains no .mwm files."));
|
||||
|
||||
size_t const numDataSources = dataSources.size();
|
||||
std::vector<uint64_t> numCountries(numDataSources);
|
||||
|
||||
for (auto const & fileName : files)
|
||||
{
|
||||
auto const fullFileName = base::JoinPath(pathToMWMFolder, fileName);
|
||||
ModelReaderPtr reader(GetPlatform().GetReader(fullFileName, "f"));
|
||||
platform::LocalCountryFile localFile(pathToMWMFolder, platform::CountryFile(base::FilenameWithoutExt(fileName)),
|
||||
version::ReadVersionDate(reader));
|
||||
|
||||
LOG(LINFO, ("Found mwm:", fullFileName));
|
||||
try
|
||||
{
|
||||
localFile.SyncWithDisk();
|
||||
for (size_t i = 0; i < numDataSources; ++i)
|
||||
{
|
||||
auto const result = dataSources[i].RegisterMap(localFile);
|
||||
CHECK_EQUAL(result.second, MwmSet::RegResult::Success, ("Can't register mwm:", localFile));
|
||||
|
||||
auto const & info = result.first.GetInfo();
|
||||
if (info && info->GetType() == MwmInfo::COUNTRY)
|
||||
++numCountries[i];
|
||||
}
|
||||
}
|
||||
catch (RootException const & ex)
|
||||
{
|
||||
CHECK(false, (ex.Msg(), "Bad mwm file:", localFile));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numDataSources; ++i)
|
||||
if (numCountries[i] == 0)
|
||||
LOG(LWARNING, ("No countries for thread", i));
|
||||
}
|
||||
|
||||
bool ValidateLimit(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value < -1)
|
||||
{
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value, "must be greater or equal to -1."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateNumThreads(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value < kMinNumThreads || value > kMaxNumThreads)
|
||||
{
|
||||
LOG(LINFO, ("Valid value for --", std::string(flagname), ":", value, "must be between", kMinNumThreads, "and",
|
||||
kMaxNumThreads));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateMwmPath(char const * flagname, std::string const & value)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
LOG(LINFO, ("--", std::string(flagname), "should be specified."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateVersion(char const * flagname, int32_t value)
|
||||
{
|
||||
if (value == 0)
|
||||
{
|
||||
LOG(LINFO, ("--", std::string(flagname), "should be specified."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value != 1 && value != 2 && value != 3)
|
||||
{
|
||||
LOG(LINFO, ("--", std::string(flagname), "should be one of 1, 2 or 3."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool const g_limitDummy = gflags::RegisterFlagValidator(&FLAGS_limit, &ValidateLimit);
|
||||
bool const g_numThreadsDummy = gflags::RegisterFlagValidator(&FLAGS_num_threads, &ValidateNumThreads);
|
||||
bool const g_mwmsPathDummy = gflags::RegisterFlagValidator(&FLAGS_mwms_path, &ValidateMwmPath);
|
||||
bool const g_algoVersion = gflags::RegisterFlagValidator(&FLAGS_algo_version, &ValidateVersion);
|
||||
|
||||
void SaveNonMatchedIds(std::string const & filename, std::vector<DecodedPath> const & paths)
|
||||
{
|
||||
if (filename.empty())
|
||||
return;
|
||||
|
||||
std::ofstream ofs(filename);
|
||||
for (auto const & p : paths)
|
||||
if (p.m_path.empty())
|
||||
ofs << p.m_segmentId << std::endl;
|
||||
}
|
||||
|
||||
std::vector<LinearSegment> LoadSegments(pugi::xml_document & document)
|
||||
{
|
||||
std::vector<LinearSegment> segments;
|
||||
if (!ParseOpenlr(document, segments))
|
||||
{
|
||||
LOG(LERROR, ("Can't parse data."));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
OpenLRDecoder::SegmentsFilter filter(FLAGS_ids_path, FLAGS_multipoints_only);
|
||||
if (FLAGS_limit != kHandleAllSegments && FLAGS_limit >= 0 && static_cast<size_t>(FLAGS_limit) < segments.size())
|
||||
segments.resize(FLAGS_limit);
|
||||
|
||||
base::EraseIf(segments, [&filter](LinearSegment const & segment) { return !filter.Matches(segment); });
|
||||
|
||||
std::sort(segments.begin(), segments.end(), base::LessBy(&LinearSegment::m_segmentId));
|
||||
|
||||
return segments;
|
||||
}
|
||||
|
||||
void WriteAssessmentFile(std::string const fileName, pugi::xml_document const & doc,
|
||||
std::vector<DecodedPath> const & paths)
|
||||
{
|
||||
std::unordered_map<uint32_t, pugi::xml_node> xmlSegments;
|
||||
for (auto const & xpathNode : doc.select_nodes("//reportSegments"))
|
||||
{
|
||||
auto const xmlSegment = xpathNode.node();
|
||||
xmlSegments[xmlSegment.child("ReportSegmentID").text().as_uint()] = xmlSegment;
|
||||
}
|
||||
|
||||
pugi::xml_document result;
|
||||
auto segments = result.append_child("Segments");
|
||||
auto const dict = doc.select_node(".//Dictionary").node();
|
||||
char const xmlns[] = "xmlns";
|
||||
|
||||
// Copy namespaces from <Dictionary> to <Segments>
|
||||
for (auto const & attr : dict.attributes())
|
||||
{
|
||||
if (strncmp(xmlns, attr.name(), sizeof(xmlns) - 1) != 0)
|
||||
continue;
|
||||
|
||||
// Don't copy default namespace.
|
||||
if (strncmp(xmlns, attr.name(), sizeof(xmlns)) == 0)
|
||||
continue;
|
||||
|
||||
segments.append_copy(attr);
|
||||
}
|
||||
|
||||
for (auto const & p : paths)
|
||||
{
|
||||
auto segment = segments.append_child("Segment");
|
||||
{
|
||||
auto const xmlSegment = xmlSegments[p.m_segmentId.Get()];
|
||||
segment.append_copy(xmlSegment);
|
||||
}
|
||||
if (!p.m_path.empty())
|
||||
{
|
||||
auto node = segment.append_child("Route");
|
||||
openlr::PathToXML(p.m_path, node);
|
||||
}
|
||||
}
|
||||
|
||||
result.save_file(fileName.data(), " " /* indent */);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
gflags::SetUsageMessage("OpenLR stats tool.");
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (!FLAGS_resources_path.empty())
|
||||
GetPlatform().SetResourceDir(FLAGS_resources_path);
|
||||
|
||||
classificator::Load();
|
||||
|
||||
auto const numThreads = static_cast<uint32_t>(FLAGS_num_threads);
|
||||
|
||||
std::vector<FrozenDataSource> dataSources(numThreads);
|
||||
|
||||
LoadDataSources(FLAGS_mwms_path, dataSources);
|
||||
|
||||
OpenLRDecoder decoder(dataSources,
|
||||
storage::CountryParentGetter(FLAGS_countries_filename, GetPlatform().ResourcesDir()));
|
||||
|
||||
pugi::xml_document document;
|
||||
auto const load_result = document.load_file(FLAGS_input.data());
|
||||
if (!load_result)
|
||||
{
|
||||
LOG(LERROR, ("Can't load file", FLAGS_input, ":", load_result.description()));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
std::setlocale(LC_ALL, "en_US.UTF-8");
|
||||
auto const segments = LoadSegments(document);
|
||||
|
||||
std::vector<DecodedPath> paths(segments.size());
|
||||
switch (FLAGS_algo_version)
|
||||
{
|
||||
case 2: decoder.DecodeV2(segments, numThreads, paths); break;
|
||||
case 3: decoder.DecodeV3(segments, numThreads, paths); break;
|
||||
default: CHECK(false, ("Wrong algorithm version."));
|
||||
}
|
||||
|
||||
SaveNonMatchedIds(FLAGS_non_matched_ids, paths);
|
||||
if (!FLAGS_assessment_output.empty())
|
||||
WriteAssessmentFile(FLAGS_assessment_output, document, paths);
|
||||
if (!FLAGS_spark_output.empty())
|
||||
WriteAsMappingForSpark(FLAGS_spark_output, paths);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue