[search] Fixed "relaxed" street matching.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
parent
28e2bd2fe2
commit
f52220ab61
4 changed files with 63 additions and 5 deletions
|
@ -1220,10 +1220,12 @@ void Geocoder::ProcessStreets(BaseContext & ctx, CentersFilter const & centers,
|
|||
vector<PredictionT> predictions;
|
||||
StreetsMatcher::Go(ctx, streets, *m_filter, m_params, predictions);
|
||||
|
||||
// Iterating from best to worst predictions here. Make "Relaxed" results for the best prediction only
|
||||
// to avoid dummy streets results, matched by very _common_ tokens.
|
||||
// Iterating from best to worst predictions here. Make "Relaxed" results for the best probability.
|
||||
for (size_t i = 0; i < predictions.size(); ++i)
|
||||
CreateStreetsLayerAndMatchLowerLayers(ctx, predictions[i], centers, i == 0 /* makeRelaxed */);
|
||||
{
|
||||
CreateStreetsLayerAndMatchLowerLayers(ctx, predictions[i], centers,
|
||||
predictions[0].SameForRelaxedMatch(predictions[i]) /* makeRelaxed */);
|
||||
}
|
||||
}
|
||||
|
||||
void Geocoder::GreedilyMatchStreetsWithSuburbs(BaseContext & ctx, CentersFilter const & centers)
|
||||
|
|
|
@ -3417,4 +3417,42 @@ UNIT_CLASS_TEST(ProcessorTest, StreetCategories)
|
|||
}
|
||||
}
|
||||
|
||||
// https://github.com/organicmaps/organicmaps/issues/4421
|
||||
UNIT_CLASS_TEST(ProcessorTest, BarcelonaStreet)
|
||||
{
|
||||
TestStreet street({{-1, -1}, {1, 1}}, "Carrer de la Concòrdia", "default");
|
||||
street.SetType({"highway", "residential"});
|
||||
TestStreet highway({{-0.9, -0.9}, {0.9, -0.9}}, "C-59 Carretera de Mollet", "default");
|
||||
highway.SetType({"highway", "trunk"});
|
||||
highway.SetRoadNumber("C-59");
|
||||
|
||||
auto wonderlandId = BuildCountry("Wonderland", [&](TestMwmBuilder & builder)
|
||||
{
|
||||
builder.Add(street);
|
||||
builder.Add(highway);
|
||||
});
|
||||
|
||||
SetViewport(m2::RectD(-0.5, -0.5, 0.5, 0.5));
|
||||
|
||||
{
|
||||
Rules const rules = {
|
||||
ExactMatch(wonderlandId, street),
|
||||
// 1 token match is discarded for _relaxed_
|
||||
//ExactMatch(wonderlandId, highway),
|
||||
};
|
||||
TEST(OrderedResultsMatch(MakeRequest("carrer de concordia 59", "en")->Results(), rules), ());
|
||||
// Add some misspellings.
|
||||
TEST(OrderedResultsMatch(MakeRequest("carrer concoria 59", "en")->Results(), rules), ());
|
||||
TEST(OrderedResultsMatch(MakeRequest("carer la concoria 59", "en")->Results(), rules), ());
|
||||
}
|
||||
|
||||
{
|
||||
Rules const rules = {
|
||||
ExactMatch(wonderlandId, street),
|
||||
ExactMatch(wonderlandId, highway),
|
||||
};
|
||||
TEST(OrderedResultsMatch(MakeRequest("concordia 59", "en")->Results(), rules), ());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace processor_test
|
||||
|
|
|
@ -178,7 +178,11 @@ void StreetsMatcher::Go(BaseContext const & ctx, CBV const & candidates,
|
|||
//
|
||||
// That's why we need all predictions here.
|
||||
|
||||
sort(predictions.rbegin(), predictions.rend(), base::LessBy(&Prediction::m_prob));
|
||||
sort(predictions.begin(), predictions.end(), [](Prediction const & l, Prediction const & r)
|
||||
{
|
||||
return l.IsBetter(r);
|
||||
});
|
||||
|
||||
while (predictions.size() > kMaxNumOfImprobablePredictions &&
|
||||
predictions.back().m_prob < kTailProbability)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,21 @@ class StreetsMatcher
|
|||
public:
|
||||
struct Prediction
|
||||
{
|
||||
inline size_t GetNumTokens() const { return m_tokenRange.Size(); }
|
||||
size_t GetNumTokens() const { return m_tokenRange.Size(); }
|
||||
|
||||
/// @todo Check m_withMisprints ?
|
||||
/// @{
|
||||
bool SameForRelaxedMatch(Prediction const & rhs) const
|
||||
{
|
||||
return m_prob == rhs.m_prob && GetNumTokens() == rhs.GetNumTokens();
|
||||
}
|
||||
bool IsBetter(Prediction const & rhs) const
|
||||
{
|
||||
if (m_prob == rhs.m_prob)
|
||||
return GetNumTokens() > rhs.GetNumTokens();
|
||||
return m_prob > rhs.m_prob;
|
||||
}
|
||||
/// @}
|
||||
|
||||
CBV m_features;
|
||||
TokenRange m_tokenRange;
|
||||
|
|
Reference in a new issue