From 3db30ffe8da06b6ed03d221dc432ca3619aeff4a Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Fri, 23 Apr 2021 17:31:24 +0200 Subject: [PATCH] Fix 393 --- .../net/osmand/search/core/SearchPhrase.java | 40 ++++++----- .../net/osmand/search/core/SearchResult.java | 66 +++++++++++++++---- .../net/osmand/search/SearchUICoreTest.java | 5 +- 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java index 09dcdc372b..9a59511711 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchPhrase.java @@ -1,20 +1,6 @@ package net.osmand.search.core; -import net.osmand.Collator; -import net.osmand.CollatorStringMatcher;import net.osmand.OsmAndCollator; -import net.osmand.CollatorStringMatcher.StringMatcherMode; -import net.osmand.StringMatcher; -import net.osmand.binary.BinaryMapIndexReader; -import net.osmand.binary.BinaryMapIndexReader.SearchRequest; -import net.osmand.binary.CommonWords; -import net.osmand.data.LatLon; -import net.osmand.data.QuadRect; -import net.osmand.util.Algorithms; -import net.osmand.util.LocationParser; -import net.osmand.util.MapUtils; - import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -26,6 +12,20 @@ import java.util.Set; import java.util.TreeSet; import java.util.regex.Pattern; +import net.osmand.Collator; +import net.osmand.CollatorStringMatcher; +import net.osmand.CollatorStringMatcher.StringMatcherMode; +import net.osmand.OsmAndCollator; +import net.osmand.StringMatcher; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.CommonWords; +import net.osmand.data.LatLon; +import net.osmand.data.QuadRect; +import net.osmand.util.Algorithms; +import net.osmand.util.LocationParser; +import net.osmand.util.MapUtils; + // Immutable object ! public class SearchPhrase { public static final String DELIMITER = " "; @@ -228,7 +228,17 @@ public class SearchPhrase { return sp; } - public int countWords(String w) { + public static void splitWords(String w, Collection ws) { + if (!Algorithms.isEmpty(w)) { + String[] wrs = w.split(ALLDELIMITERS); + for (int i = 0; i < wrs.length; i++) { + String wd = wrs[i].trim(); + ws.add(wd); + } + } + } + + public static int countWords(String w) { int cnt = 0; if (!Algorithms.isEmpty(w)) { String[] ws = w.split(ALLDELIMITERS); diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchResult.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchResult.java index 8d1df0a41a..816e15d806 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchResult.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchResult.java @@ -1,5 +1,9 @@ package net.osmand.search.core; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.City; import net.osmand.data.LatLon; @@ -11,8 +15,6 @@ import net.osmand.osm.PoiType; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; -import java.util.Collection; - public class SearchResult { // search phrase that makes search result valid public SearchPhrase requiredSearchPhrase; @@ -41,6 +43,8 @@ public class SearchResult { public String localeRelatedObjectName; public Object relatedObject; public double distRelatedObjectName; + + private double unknownPhraseMatchWeight = 0; public SearchResult(SearchPhrase sp) { this.requiredSearchPhrase = sp; @@ -49,29 +53,65 @@ public class SearchResult { // maximum corresponds to the top entry public double getUnknownPhraseMatchWeight() { + if (unknownPhraseMatchWeight != 0) { + return unknownPhraseMatchWeight; + } // if result is a complete match in the search we prioritize it higher - return getSumPhraseMatchWeight() / Math.pow(MAX_TYPE_WEIGHT, getDepth() - 1); + double res = getSumPhraseMatchWeight() / Math.pow(MAX_TYPE_WEIGHT, getDepth() - 1); + unknownPhraseMatchWeight = res; + return res; } public double getSumPhraseMatchWeight() { // if result is a complete match in the search we prioritize it higher - String name = alternateName != null? alternateName : localeName; - int localWordsMatched = requiredSearchPhrase.countWords(name) ; - boolean match = localWordsMatched <= getSelfWordCount(); - boolean fullCompleteMatch = false; - double res = 1; - if (match) { - res = ObjectType.getTypeWeight(match ? objectType : null); - fullCompleteMatch = getSelfPhrase().equalsIgnoreCase(name); - if (fullCompleteMatch) { - res = res * 10; + String name = alternateName != null ? alternateName : localeName; + List localResultNames = new ArrayList<>(); + SearchPhrase.splitWords(name, localResultNames); + List searchPhraseNames = new ArrayList(); + if (firstUnknownWordMatches) { + searchPhraseNames.add(requiredSearchPhrase.getFirstUnknownSearchWord()); + } + if (otherWordsMatch != null) { + searchPhraseNames.addAll(otherWordsMatch); + } + int idxMatchedWord = -1; + boolean allWordsMatched = true; + if (!checkPhraseIsObjectType()) { + for (int i = 0; i < searchPhraseNames.size(); i++) { + boolean wordMatched = false; + for (int j = idxMatchedWord + 1; j < localResultNames.size(); j++) { + int r = requiredSearchPhrase.getCollator().compare(searchPhraseNames.get(i), localResultNames.get(j)); + if (r == 0) { + wordMatched = true; + idxMatchedWord = j; + break; + } + } + if (!wordMatched) { + allWordsMatched = false; + break; + } } } + double res = ObjectType.getTypeWeight(allWordsMatched ? objectType : null); if (parentSearchResult != null) { res = res + parentSearchResult.getSumPhraseMatchWeight() / MAX_TYPE_WEIGHT; } return res; } + + private boolean checkPhraseIsObjectType() { +// if (object instanceof Amenity) { +// String poiType = ((Amenity) object).getType().getKeyName(); +// String poiSubType = ((Amenity) object).getSubType(); +// boolean isType = poiType.equalsIgnoreCase(phrase); +// boolean isSubType = poiSubType.equalsIgnoreCase(phrase); +// return isType || isSubType; +// } + return false; + } + + public int getDepth() { if (parentSearchResult != null) { diff --git a/OsmAnd-java/src/test/java/net/osmand/search/SearchUICoreTest.java b/OsmAnd-java/src/test/java/net/osmand/search/SearchUICoreTest.java index 328b16543a..e2a7591acc 100644 --- a/OsmAnd-java/src/test/java/net/osmand/search/SearchUICoreTest.java +++ b/OsmAnd-java/src/test/java/net/osmand/search/SearchUICoreTest.java @@ -132,6 +132,10 @@ public class SearchUICoreTest { reader = new BinaryMapIndexReader(new RandomAccessFile(obfFile.getPath(), "r"), obfFile); } + boolean disabled = settingsJson.optBoolean("disabled", false); + if (disabled) { + return; + } List> results = new ArrayList<>(); for (int i = 0; i < phrases.size(); i++) { results.add(new ArrayList()); @@ -199,7 +203,6 @@ public class SearchUICoreTest { System.out.println("EXPECTED : "); for (String r : result) { System.out.println(String.format("\t\"%s\",", r)); - } } Assert.assertEquals(expected, present);