diff --git a/search/geocoder.cpp b/search/geocoder.cpp index e671bc1e1d..ffc2f9e58f 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -1557,6 +1557,33 @@ void Geocoder::EmitResult(BaseContext & ctx, MwmSet::MwmId const & mwmId, uint32 { FeatureID id(mwmId, ftId); + double matchedFraction = 1.0; + // For categorial requests |allTokensUsed| == true and matchedFraction can not be calculated from |ctx|. + if (!allTokensUsed) + { + size_t length = 0; + size_t matchedLength = 0; + TokenSlice slice(m_params, TokenRange(0, ctx.m_numTokens)); + for (size_t tokenIdx = 0; tokenIdx < ctx.m_numTokens; ++tokenIdx) + { + auto const tokenLength = slice.Get(tokenIdx).GetOriginal().size(); + length += tokenLength; + if (ctx.IsTokenUsed(tokenIdx)) + matchedLength += tokenLength; + } + CHECK_NOT_EQUAL(length, 0, ()); + + matchedFraction = static_cast(matchedLength) / static_cast(length); + } + + // In our samples the least value for matched fraction for relevant result is 0.116. + // It is "Горнолыжный комплекс Ключи" feature for "Спортивно стрелковый комплекс Ключи + // Новосибирск" query. It is relevant not found result (search does not find it, but it's + // relevant). The least matched fraction for found relevant result is 0.241935, for found vital + // result is 0.269231. + if (matchedFraction <= 0.1) + return; + if (ctx.m_hotelsFilter && !ctx.m_hotelsFilter->Matches(id)) return; diff --git a/search/search_integration_tests/processor_test.cpp b/search/search_integration_tests/processor_test.cpp index d5373b4bcd..b290caa021 100644 --- a/search/search_integration_tests/processor_test.cpp +++ b/search/search_integration_tests/processor_test.cpp @@ -2765,5 +2765,32 @@ UNIT_CLASS_TEST(ProcessorTest, FilterVillages) TEST(ResultsMatch(request.Results(), rules), ()); } } + +UNIT_CLASS_TEST(ProcessorTest, MatchedFraction) +{ + string const countryName = "Wonderland"; + string const streetName = "Октябрьский проспaект"; + + TestStreet street1(vector{m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0)}, + "Первомайская", "ru"); + TestStreet street2(vector{m2::PointD(-1.0, 1.0), m2::PointD(1.0, -1.0)}, + "8 марта", "ru"); + + auto countryId = BuildCountry(countryName, [&](TestMwmBuilder & builder) { + builder.Add(street1); + builder.Add(street2); + }); + + SetViewport(m2::RectD(-1.0, -1.0, 1.0, 1.0)); + { + // |8 марта| should not match because matched fraction is too low (1/13 <= 0.1). + Rules rules = {ExactMatch(countryId, street1)}; + TEST(ResultsMatch("первомайская 8 ", rules), ()); + } + { + Rules rules = {ExactMatch(countryId, street2)}; + TEST(ResultsMatch("8 ", rules), ()); + } +} } // namespace } // namespace search