Merge remote-tracking branch 'origin/master' into map_source_dialog_7658
# Conflicts: # OsmAnd/res/values/strings.xml
|
@ -29,6 +29,7 @@ import java.util.TreeSet;
|
|||
|
||||
|
||||
public class MapPoiTypes {
|
||||
private static final String OTHER_MAP_CATEGORY = "Other";
|
||||
private static MapPoiTypes DEFAULT_INSTANCE = null;
|
||||
private static final Log log = PlatformUtil.getLog(MapRenderingTypes.class);
|
||||
private String resourceName;
|
||||
|
@ -96,7 +97,7 @@ public class MapPoiTypes {
|
|||
|
||||
public PoiCategory getOtherMapCategory() {
|
||||
if (otherMapCategory == null) {
|
||||
otherMapCategory = getPoiCategoryByName("Other", true);
|
||||
otherMapCategory = getPoiCategoryByName(OTHER_MAP_CATEGORY, true);
|
||||
}
|
||||
return otherMapCategory;
|
||||
}
|
||||
|
@ -111,7 +112,8 @@ public class MapPoiTypes {
|
|||
|
||||
public List<AbstractPoiType> getTopVisibleFilters() {
|
||||
List<AbstractPoiType> lf = new ArrayList<AbstractPoiType>();
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
if (pc.isTopVisible()) {
|
||||
lf.add(pc);
|
||||
}
|
||||
|
@ -131,7 +133,8 @@ public class MapPoiTypes {
|
|||
}
|
||||
|
||||
public PoiCategory getOsmwiki() {
|
||||
for (PoiCategory category : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory category = categories.get(i);
|
||||
if (category.isWiki()) {
|
||||
return category;
|
||||
}
|
||||
|
@ -167,7 +170,8 @@ public class MapPoiTypes {
|
|||
}
|
||||
|
||||
public PoiType getPoiTypeByKey(String name) {
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
PoiType pt = pc.getPoiTypeByKeyName(name);
|
||||
if (pt != null && !pt.isReference()) {
|
||||
return pt;
|
||||
|
@ -184,7 +188,8 @@ public class MapPoiTypes {
|
|||
}
|
||||
|
||||
public AbstractPoiType getAnyPoiTypeByKey(String name) {
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
if (pc.getKeyName().equals(name)) {
|
||||
return pc;
|
||||
}
|
||||
|
@ -203,7 +208,8 @@ public class MapPoiTypes {
|
|||
|
||||
public Map<String, PoiType> getAllTranslatedNames(boolean skipNonEditable) {
|
||||
Map<String, PoiType> translation = new HashMap<String, PoiType>();
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
if (skipNonEditable && pc.isNotEditableOsm()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -231,7 +237,8 @@ public class MapPoiTypes {
|
|||
|
||||
public List<AbstractPoiType> getAllTypesTranslatedNames(StringMatcher matcher) {
|
||||
List<AbstractPoiType> tm = new ArrayList<AbstractPoiType>();
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
if (pc == otherMapCategory) {
|
||||
continue;
|
||||
}
|
||||
|
@ -294,7 +301,7 @@ public class MapPoiTypes {
|
|||
}
|
||||
if (create) {
|
||||
PoiCategory lastCategory = new PoiCategory(this, name, categories.size());
|
||||
if (!lastCategory.getKeyName().equals("Other")) {
|
||||
if (!lastCategory.getKeyName().equals(OTHER_MAP_CATEGORY)) {
|
||||
lastCategory.setTopVisible(true);
|
||||
}
|
||||
addCategory(lastCategory);
|
||||
|
@ -353,6 +360,11 @@ public class MapPoiTypes {
|
|||
final Map<String, PoiType> allTypes = new LinkedHashMap<String, PoiType>();
|
||||
final Map<String, List<PoiType>> categoryPoiAdditionalMap = new LinkedHashMap<String, List<PoiType>>();
|
||||
final Map<AbstractPoiType, Set<String>> abstractTypeAdditionalCategories = new LinkedHashMap<AbstractPoiType, Set<String>>();
|
||||
final Map<String, PoiType> poiTypesByTag = new LinkedHashMap<String, PoiType>();
|
||||
final Map<String, String> deprecatedTags = new LinkedHashMap<String, String>();
|
||||
final Map<String, String> poiAdditionalCategoryIconNames = new LinkedHashMap<String, String>();
|
||||
final List<PoiType> textPoiAdditionals = new ArrayList<PoiType>();
|
||||
|
||||
List<PoiCategory> categoriesList = new ArrayList<>();
|
||||
try {
|
||||
XmlPullParser parser = PlatformUtil.newXMLPullParser();
|
||||
|
@ -365,6 +377,8 @@ public class MapPoiTypes {
|
|||
PoiType lastType = null;
|
||||
Set<String> lastTypePoiAdditionalsCategories = new TreeSet<String>();
|
||||
String lastPoiAdditionalCategory = null;
|
||||
PoiCategory localOtherMapCategory = new PoiCategory(this, OTHER_MAP_CATEGORY, categoriesList.size());
|
||||
categoriesList.add(localOtherMapCategory);
|
||||
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
if (tok == XmlPullParser.START_TAG) {
|
||||
String name = parser.getName();
|
||||
|
@ -404,14 +418,17 @@ public class MapPoiTypes {
|
|||
lastCategory.addPoiType(tp);
|
||||
} else if (name.equals("poi_additional")) {
|
||||
if (lastCategory == null) {
|
||||
lastCategory = getOtherMapCategory();
|
||||
lastCategory = localOtherMapCategory;
|
||||
}
|
||||
PoiType baseType = parsePoiAdditional(parser, lastCategory, lastFilter, lastType, null, null, lastPoiAdditionalCategory);
|
||||
PoiType baseType = parsePoiAdditional(parser, lastCategory, lastFilter, lastType, null, null,
|
||||
lastPoiAdditionalCategory, textPoiAdditionals);
|
||||
if ("true".equals(parser.getAttributeValue("", "lang"))) {
|
||||
for (String lng : MapRenderingTypes.langs) {
|
||||
parsePoiAdditional(parser, lastCategory, lastFilter, lastType, lng, baseType, lastPoiAdditionalCategory);
|
||||
parsePoiAdditional(parser, lastCategory, lastFilter, lastType, lng, baseType,
|
||||
lastPoiAdditionalCategory, textPoiAdditionals);
|
||||
}
|
||||
parsePoiAdditional(parser, lastCategory, lastFilter, lastType, "en", baseType, lastPoiAdditionalCategory);
|
||||
parsePoiAdditional(parser, lastCategory, lastFilter, lastType, "en", baseType,
|
||||
lastPoiAdditionalCategory, textPoiAdditionals);
|
||||
}
|
||||
if (lastPoiAdditionalCategory != null) {
|
||||
List<PoiType> categoryAdditionals = categoryPoiAdditionalMap.get(lastPoiAdditionalCategory);
|
||||
|
@ -433,7 +450,7 @@ public class MapPoiTypes {
|
|||
|
||||
} else if (name.equals("poi_type")) {
|
||||
if (lastCategory == null) {
|
||||
lastCategory = getOtherMapCategory();
|
||||
lastCategory = localOtherMapCategory;
|
||||
}
|
||||
if(!Algorithms.isEmpty(parser.getAttributeValue("", "deprecated_of"))){
|
||||
String vl = parser.getAttributeValue("", "name");
|
||||
|
@ -482,7 +499,7 @@ public class MapPoiTypes {
|
|||
}
|
||||
}
|
||||
}
|
||||
categories = categoriesList;
|
||||
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
log.error("Unexpected error", e); //$NON-NLS-1$
|
||||
|
@ -510,17 +527,25 @@ public class MapPoiTypes {
|
|||
List<PoiType> poiAdditionals = categoryPoiAdditionalMap.get(category);
|
||||
if (poiAdditionals != null) {
|
||||
for (PoiType poiType : poiAdditionals) {
|
||||
buildPoiAdditionalReference(poiType, entry.getKey());
|
||||
buildPoiAdditionalReference(poiType, entry.getKey(), textPoiAdditionals);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
findDefaultOtherCategory();
|
||||
this.categories = categoriesList;
|
||||
this.poiTypesByTag = poiTypesByTag;
|
||||
this.deprecatedTags = deprecatedTags;
|
||||
this.poiAdditionalCategoryIconNames = poiAdditionalCategoryIconNames;
|
||||
this.textPoiAdditionals = textPoiAdditionals;
|
||||
otherCategory = getPoiCategoryByName("user_defined_other");
|
||||
if (otherCategory == null) {
|
||||
throw new IllegalArgumentException("No poi category other");
|
||||
}
|
||||
init = true;
|
||||
log.info("Time to init poi types " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private PoiType buildPoiAdditionalReference(PoiType poiAdditional, AbstractPoiType parent) {
|
||||
private PoiType buildPoiAdditionalReference(PoiType poiAdditional, AbstractPoiType parent, List<PoiType> textPoiAdditionals) {
|
||||
PoiCategory lastCategory = null;
|
||||
PoiFilter lastFilter = null;
|
||||
PoiType lastType = null;
|
||||
|
@ -571,7 +596,8 @@ public class MapPoiTypes {
|
|||
}
|
||||
|
||||
private PoiType parsePoiAdditional(XmlPullParser parser, PoiCategory lastCategory, PoiFilter lastFilter,
|
||||
PoiType lastType, String lang, PoiType langBaseType, String poiAdditionalCategory) {
|
||||
PoiType lastType, String lang, PoiType langBaseType,
|
||||
String poiAdditionalCategory, List<PoiType> textPoiAdditionals) {
|
||||
String oname = parser.getAttributeValue("", "name");
|
||||
if (lang != null) {
|
||||
oname += ":" + lang;
|
||||
|
@ -653,13 +679,6 @@ public class MapPoiTypes {
|
|||
return tp;
|
||||
}
|
||||
|
||||
private void findDefaultOtherCategory() {
|
||||
PoiCategory pc = getPoiCategoryByName("user_defined_other");
|
||||
if (pc == null) {
|
||||
throw new IllegalArgumentException("No poi category other");
|
||||
}
|
||||
otherCategory = pc;
|
||||
}
|
||||
|
||||
public List<PoiCategory> getCategories(boolean includeMapCategory) {
|
||||
ArrayList<PoiCategory> lst = new ArrayList<PoiCategory>(categories);
|
||||
|
@ -705,7 +724,8 @@ public class MapPoiTypes {
|
|||
|
||||
public AbstractPoiType getAnyPoiAdditionalTypeByKey(String name) {
|
||||
PoiType add = null;
|
||||
for (PoiCategory pc : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory pc = categories.get(i);
|
||||
add = getPoiAdditionalByKey(pc, name);
|
||||
if (add != null) {
|
||||
return add;
|
||||
|
@ -811,7 +831,8 @@ public class MapPoiTypes {
|
|||
if (!poiTypesByTag.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (PoiCategory poic : categories) {
|
||||
for (int i = 0; i < categories.size(); i++) {
|
||||
PoiCategory poic = categories.get(i);
|
||||
for (PoiType p : poic.getPoiTypes()) {
|
||||
initPoiType(p);
|
||||
for (PoiType pts : p.getPoiAdditionals()) {
|
||||
|
|
|
@ -652,6 +652,10 @@ public class SearchUICore {
|
|||
return prev;
|
||||
}
|
||||
|
||||
public SearchResult getParentSearchResult() {
|
||||
return parentSearchResult;
|
||||
}
|
||||
|
||||
public List<SearchResult> getRequestResults() {
|
||||
return requestResults;
|
||||
}
|
||||
|
@ -730,9 +734,9 @@ public class SearchUICore {
|
|||
object.localeName = object.alternateName;
|
||||
object.alternateName = null;
|
||||
}
|
||||
object.parentSearchResult = parentSearchResult;
|
||||
if (matcher == null || matcher.publish(object)) {
|
||||
count++;
|
||||
object.parentSearchResult = parentSearchResult;
|
||||
if (totalLimit == -1 || count < totalLimit) {
|
||||
requestResults.add(object);
|
||||
}
|
||||
|
@ -740,6 +744,7 @@ public class SearchUICore {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
boolean cancelled = request != requestNumber.get();
|
||||
|
@ -849,12 +854,121 @@ public class SearchUICore {
|
|||
}
|
||||
}
|
||||
|
||||
private enum ResultCompareStep {
|
||||
TOP_VISIBLE,
|
||||
FOUND_WORD_COUNT,
|
||||
UNKNOWN_PHRASE_MATCH_WEIGHT,
|
||||
SEARCH_DISTANCE_IF_NOT_BY_NAME,
|
||||
COMPARE_FIRST_NUMBER_IN_NAME,
|
||||
COMPARE_DISTANCE_TO_PARENT_SEARCH_RESULT, // makes sense only for inner subqueries
|
||||
COMPARE_BY_NAME,
|
||||
COMPARE_BY_DISTANCE,
|
||||
AMENITY_LAST_AND_SORT_BY_SUBTYPE
|
||||
;
|
||||
|
||||
// -1 - means 1st is less (higher) than 2nd
|
||||
public int compare(SearchResult o1, SearchResult o2, SearchResultComparator c) {
|
||||
switch(this) {
|
||||
case TOP_VISIBLE:
|
||||
boolean topVisible1 = ObjectType.isTopVisible(o1.objectType);
|
||||
boolean topVisible2 = ObjectType.isTopVisible(o2.objectType);
|
||||
if (topVisible1 != topVisible2) {
|
||||
// -1 - means 1st is less than 2nd
|
||||
return topVisible1 ? -1 : 1;
|
||||
}
|
||||
break;
|
||||
case FOUND_WORD_COUNT:
|
||||
if (o1.getFoundWordCount() != o2.getFoundWordCount()) {
|
||||
return -Algorithms.compare(o1.getFoundWordCount(), o2.getFoundWordCount());
|
||||
}
|
||||
break;
|
||||
case UNKNOWN_PHRASE_MATCH_WEIGHT:
|
||||
// here we check how much each sub search result matches the phrase
|
||||
// also we sort it by type house -> street/poi -> city/postcode/village/other
|
||||
if (o1.getUnknownPhraseMatchWeight() != o2.getUnknownPhraseMatchWeight()) {
|
||||
return -Double.compare(o1.getUnknownPhraseMatchWeight(), o2.getUnknownPhraseMatchWeight());
|
||||
}
|
||||
break;
|
||||
case SEARCH_DISTANCE_IF_NOT_BY_NAME:
|
||||
if (!c.sortByName) {
|
||||
double s1 = o1.getSearchDistance(c.loc);
|
||||
double s2 = o2.getSearchDistance(c.loc);
|
||||
if (s1 != s2) {
|
||||
return Double.compare(s1, s2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COMPARE_FIRST_NUMBER_IN_NAME: {
|
||||
String localeName1 = o1.localeName == null ? "" : o1.localeName;
|
||||
String localeName2 = o2.localeName == null ? "" : o2.localeName;
|
||||
int st1 = Algorithms.extractFirstIntegerNumber(localeName1);
|
||||
int st2 = Algorithms.extractFirstIntegerNumber(localeName2);
|
||||
if (st1 != st2) {
|
||||
return Algorithms.compare(st1, st2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMPARE_DISTANCE_TO_PARENT_SEARCH_RESULT:
|
||||
double ps1 = o1.parentSearchResult == null ? 0 : o1.parentSearchResult.getSearchDistance(c.loc);
|
||||
double ps2 = o2.parentSearchResult == null ? 0 : o2.parentSearchResult.getSearchDistance(c.loc);
|
||||
if (ps1 != ps2) {
|
||||
return Double.compare(ps1, ps2);
|
||||
}
|
||||
break;
|
||||
case COMPARE_BY_NAME: {
|
||||
String localeName1 = o1.localeName == null ? "" : o1.localeName;
|
||||
String localeName2 = o2.localeName == null ? "" : o2.localeName;
|
||||
int cmp = c.collator.compare(localeName1, localeName2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COMPARE_BY_DISTANCE:
|
||||
double s1 = o1.getSearchDistance(c.loc, 1);
|
||||
double s2 = o2.getSearchDistance(c.loc, 1);
|
||||
if (s1 != s2) {
|
||||
return Double.compare(s1, s2);
|
||||
}
|
||||
break;
|
||||
case AMENITY_LAST_AND_SORT_BY_SUBTYPE: {
|
||||
boolean am1 = o1.object instanceof Amenity;
|
||||
boolean am2 = o2.object instanceof Amenity;
|
||||
if (am1 != am2) {
|
||||
// amenity second
|
||||
return am1 ? 1 : -1;
|
||||
} else if (am1 && am2) {
|
||||
// here 2 points are amenity
|
||||
Amenity a1 = (Amenity) o1.object;
|
||||
Amenity a2 = (Amenity) o2.object;
|
||||
String type1 = a1.getType().getKeyName();
|
||||
String type2 = a2.getType().getKeyName();
|
||||
int cmp = c.collator.compare(type1, type2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
String subType1 = a1.getSubType() == null ? "" : a1.getSubType();
|
||||
String subType2 = a2.getSubType() == null ? "" : a2.getSubType();
|
||||
cmp = c.collator.compare(subType1, subType2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchResultComparator implements Comparator<SearchResult> {
|
||||
private SearchPhrase sp;
|
||||
private Collator collator;
|
||||
private LatLon loc;
|
||||
private boolean sortByName;
|
||||
|
||||
|
||||
public SearchResultComparator(SearchPhrase sp) {
|
||||
this.sp = sp;
|
||||
this.collator = sp.getCollator();
|
||||
|
@ -865,66 +979,10 @@ public class SearchUICore {
|
|||
|
||||
@Override
|
||||
public int compare(SearchResult o1, SearchResult o2) {
|
||||
boolean topVisible1 = ObjectType.isTopVisible(o1.objectType);
|
||||
boolean topVisible2 = ObjectType.isTopVisible(o2.objectType);
|
||||
if (topVisible1 != topVisible2) {
|
||||
// -1 - means 1st is less than 2nd
|
||||
return topVisible1 ? -1 : 1;
|
||||
}
|
||||
if (o1.getUnknownPhraseMatchWeight() != o2.getUnknownPhraseMatchWeight()) {
|
||||
return -Double.compare(o1.getUnknownPhraseMatchWeight(), o2.getUnknownPhraseMatchWeight());
|
||||
}
|
||||
if (o1.getFoundWordCount() != o2.getFoundWordCount()) {
|
||||
return -Algorithms.compare(o1.getFoundWordCount(), o2.getFoundWordCount());
|
||||
}
|
||||
if (!sortByName) {
|
||||
double s1 = o1.getSearchDistance(loc);
|
||||
double s2 = o2.getSearchDistance(loc);
|
||||
if (s1 != s2) {
|
||||
return Double.compare(s1, s2);
|
||||
}
|
||||
}
|
||||
String localeName1 = o1.localeName == null ? "" : o1.localeName;
|
||||
String localeName2 = o2.localeName == null ? "" : o2.localeName;
|
||||
int st1 = Algorithms.extractFirstIntegerNumber(localeName1);
|
||||
int st2 = Algorithms.extractFirstIntegerNumber(localeName2);
|
||||
if (st1 != st2) {
|
||||
return Algorithms.compare(st1, st2);
|
||||
}
|
||||
double s1 = o1.getSearchDistance(loc, 1);
|
||||
double s2 = o2.getSearchDistance(loc, 1);
|
||||
double ps1 = o1.parentSearchResult == null ? 0 : o1.parentSearchResult.getSearchDistance(loc);
|
||||
double ps2 = o2.parentSearchResult == null ? 0 : o2.parentSearchResult.getSearchDistance(loc);
|
||||
if (ps1 != ps2) {
|
||||
return Double.compare(ps1, ps2);
|
||||
}
|
||||
int cmp = collator.compare(localeName1, localeName2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
if (s1 != s2) {
|
||||
return Double.compare(s1, s2);
|
||||
}
|
||||
boolean am1 = o1.object instanceof Amenity;
|
||||
boolean am2 = o2.object instanceof Amenity;
|
||||
if (am1 != am2) {
|
||||
return Boolean.compare(am1, am2);
|
||||
} else if (am1 && am2) {
|
||||
// here 2 points are amenity
|
||||
Amenity a1 = (Amenity) o1.object;
|
||||
Amenity a2 = (Amenity) o2.object;
|
||||
String type1 = a1.getType().getKeyName();
|
||||
String type2 = a2.getType().getKeyName();
|
||||
cmp = collator.compare(type1, type2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
String subType1 = a1.getSubType() == null ? "" : a1.getSubType();
|
||||
String subType2 = a2.getSubType() == null ? "" : a2.getSubType();
|
||||
cmp = collator.compare(subType1, subType2);
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
for(ResultCompareStep step : ResultCompareStep.values()) {
|
||||
int r = step.compare(o1, o2, this);
|
||||
if(r != 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -45,27 +45,24 @@ public enum ObjectType {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static double getTypeWeight(ObjectType t) {
|
||||
public static int getTypeWeight(ObjectType t) {
|
||||
if (t == null) {
|
||||
return 1.0;
|
||||
return 1;
|
||||
}
|
||||
switch (t) {
|
||||
case CITY:
|
||||
return 1.0;
|
||||
case VILLAGE:
|
||||
return 1.0;
|
||||
case POSTCODE:
|
||||
return 1.0;
|
||||
case STREET:
|
||||
return 2.0;
|
||||
case HOUSE:
|
||||
return 3.0;
|
||||
case STREET_INTERSECTION:
|
||||
return 3.0;
|
||||
return 4;
|
||||
case STREET:
|
||||
return 3;
|
||||
case POI:
|
||||
return 2.0;
|
||||
return 2;
|
||||
case CITY:
|
||||
case VILLAGE:
|
||||
case POSTCODE:
|
||||
return 1;
|
||||
default:
|
||||
return 1.0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,14 +154,10 @@ public class SearchCoreFactory {
|
|||
if (!ws.isEmpty() && api != null && api.isSearchAvailable(phrase)) {
|
||||
SearchPhrase nphrase = phrase.selectWord(res, ws,
|
||||
phrase.isLastUnknownSearchWordComplete());
|
||||
SearchResult prev = resultMatcher.setParentSearchResult(res);
|
||||
res.parentSearchResult = prev;
|
||||
resultMatcher.setParentSearchResult(res);
|
||||
api.search(nphrase, resultMatcher);
|
||||
resultMatcher.setParentSearchResult(prev);
|
||||
resultMatcher.setParentSearchResult(res.parentSearchResult);
|
||||
}
|
||||
// if (resultMatcher.getCount() == cnt) {
|
||||
// resultMatcher.publish(res);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -121,7 +121,12 @@ public class SearchPhrase {
|
|||
int i1 = CommonWords.getCommonSearch(o1.toLowerCase());
|
||||
int i2 = CommonWords.getCommonSearch(o2.toLowerCase());
|
||||
if (i1 != i2) {
|
||||
return icompare(i1, i2);
|
||||
if(i1 == -1) {
|
||||
return -1;
|
||||
} else if(i2 == -1) {
|
||||
return 1;
|
||||
}
|
||||
return -icompare(i1, i2);
|
||||
}
|
||||
// compare length without numbers to not include house numbers
|
||||
return -icompare(lengthWithoutNumbers(o1), lengthWithoutNumbers(o2));
|
||||
|
@ -465,13 +470,17 @@ public class SearchPhrase {
|
|||
sp.words.addAll(0, this.words);
|
||||
if (unknownWords != null) {
|
||||
sp.lastUnknownSearchWordComplete = lastComplete;
|
||||
StringBuilder genUnknownSearchPhrase = new StringBuilder();
|
||||
for (int i = 0; i < unknownWords.size(); i++) {
|
||||
if (i == 0) {
|
||||
sp.unknownSearchWordTrim = unknownWords.get(0);
|
||||
} else {
|
||||
sp.unknownWords.add(unknownWords.get(i));
|
||||
}
|
||||
genUnknownSearchPhrase.append(unknownWords.get(i)).append(" ");
|
||||
}
|
||||
|
||||
sp.rawUnknownSearchPhrase = sp.unknownSearchPhrase = genUnknownSearchPhrase.toString().trim();
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
@ -728,8 +737,9 @@ public class SearchPhrase {
|
|||
for (int i = 0; i < unknownWords.size(); i++) {
|
||||
if (unknownWordsMatcher.size() == i) {
|
||||
unknownWordsMatcher.add(new NameStringMatcher(unknownWords.get(i),
|
||||
i < unknownWords.size() - 1 || isLastUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE :
|
||||
StringMatcherMode.CHECK_STARTS_FROM_SPACE));
|
||||
i < unknownWords.size() - 1 || isLastUnknownSearchWordComplete()
|
||||
? StringMatcherMode.CHECK_EQUALS_FROM_SPACE
|
||||
: StringMatcherMode.CHECK_STARTS_FROM_SPACE));
|
||||
}
|
||||
NameStringMatcher ms = unknownWordsMatcher.get(i);
|
||||
if (ms.matches(localeName) || ms.matches(otherNames)) {
|
||||
|
|
|
@ -34,17 +34,15 @@ public class SearchResult {
|
|||
}
|
||||
|
||||
public double getUnknownPhraseMatchWeight() {
|
||||
return getUnknownPhraseMatchWeight(false);
|
||||
}
|
||||
|
||||
private double getUnknownPhraseMatchWeight(boolean isHouse) {
|
||||
// if result is a complete match in the search we prioritize it highers
|
||||
double res = 0;
|
||||
isHouse = isHouse || objectType == ObjectType.HOUSE;
|
||||
if (unknownPhraseMatches) {
|
||||
res = isHouse ? ObjectType.getTypeWeight(ObjectType.HOUSE) : ObjectType.getTypeWeight(objectType);
|
||||
res = ObjectType.getTypeWeight(objectType);
|
||||
}
|
||||
if (res == 0 && parentSearchResult != null) {
|
||||
return parentSearchResult.getUnknownPhraseMatchWeight(isHouse);
|
||||
if (parentSearchResult != null) {
|
||||
// 10 > maximum type
|
||||
// res = Math.max(res,parentSearchResult.getUnknownPhraseMatchWeight()) ;
|
||||
res += parentSearchResult.getUnknownPhraseMatchWeight() / 10;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package net.osmand.search;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.search.SearchUICore.SearchResultCollection;
|
||||
import net.osmand.search.core.SearchPhrase;
|
||||
import net.osmand.search.core.SearchResult;
|
||||
import net.osmand.search.core.SearchSettings;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
public class SearchUICoreGenericTest {
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
SearchUICoreTest.defaultSetup();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDuplicates() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, true, true);
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoResort() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(2));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoResortDuplicate() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(2));
|
||||
}
|
||||
|
||||
private SearchResult searchResult(List<SearchResult> rs, SearchPhrase phrase, String text, int dist) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = text;
|
||||
double d1 = MapUtils.getDistance(0, 0, 0, 1);
|
||||
res.location = new LatLon(0, dist / d1);
|
||||
rs.add(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,12 +1,30 @@
|
|||
package net.osmand.search;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import net.osmand.OsmAndCollator;
|
||||
import net.osmand.ResultMatcher;
|
||||
import net.osmand.binary.BinaryMapIndexReader;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.data.Building;
|
||||
import net.osmand.data.City;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.MapObject;
|
||||
import net.osmand.data.Street;
|
||||
import net.osmand.osm.AbstractPoiType;
|
||||
|
@ -17,35 +35,31 @@ import net.osmand.search.core.SearchPhrase;
|
|||
import net.osmand.search.core.SearchResult;
|
||||
import net.osmand.search.core.SearchSettings;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class SearchCoreUITest {
|
||||
@RunWith(Parameterized.class)
|
||||
public class SearchUICoreTest {
|
||||
|
||||
private static final String SEARCH_RESOURCES_PATH = "src/test/resources/search/";
|
||||
private static Map<String, String> enPhrases = new HashMap<>();
|
||||
private static Map<String, String> phrases = new HashMap<>();
|
||||
private static boolean TEST_EXTRA_RESULTS = true;
|
||||
|
||||
static {
|
||||
private File testFile;
|
||||
|
||||
public SearchUICoreTest(String name, File file) {
|
||||
this.testFile = file;
|
||||
}
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
defaultSetup();
|
||||
}
|
||||
|
||||
|
||||
static void defaultSetup() {
|
||||
MapPoiTypes.setDefault(new MapPoiTypes("src/test/resources/poi_types.xml"));
|
||||
MapPoiTypes poiTypes = MapPoiTypes.getDefault();
|
||||
|
||||
Map<String, String> enPhrases = new HashMap<>();
|
||||
Map<String, String> phrases = new HashMap<>();
|
||||
try {
|
||||
enPhrases = Algorithms.parseStringsXml(new File("src/test/resources/phrases/en/phrases.xml"));
|
||||
//phrases = Algorithms.parseStringsXml(new File("src/test/resources/phrases/ru/phrases.xml"));
|
||||
|
@ -56,7 +70,139 @@ public class SearchCoreUITest {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
poiTypes.setPoiTranslator(new MapPoiTypes.PoiTranslator() {
|
||||
poiTypes.setPoiTranslator(new TestSearchTranslator(phrases, enPhrases));
|
||||
}
|
||||
|
||||
|
||||
@Parameterized.Parameters(name = "{index}: {0}")
|
||||
public static Iterable<Object[]> data() throws IOException {
|
||||
final File[] files = new File(SEARCH_RESOURCES_PATH).listFiles();
|
||||
ArrayList<Object[]> arrayList = new ArrayList<>();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
if(fileName.endsWith(".json")) {
|
||||
String name = fileName.substring(0, fileName.length() - ".json".length());
|
||||
arrayList.add(new Object[] {name, file});
|
||||
}
|
||||
}
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearch() throws IOException, JSONException {
|
||||
File jsonFile = testFile;
|
||||
String sourceJsonText = Algorithms.getFileAsString(jsonFile);
|
||||
Assert.assertNotNull(sourceJsonText);
|
||||
Assert.assertTrue(sourceJsonText.length() > 0);
|
||||
|
||||
BinaryMapIndexReaderTest reader = new BinaryMapIndexReaderTest();
|
||||
JSONObject sourceJson = new JSONObject(sourceJsonText);
|
||||
String phraseText = sourceJson.getString("phrase");
|
||||
JSONObject settingsJson = sourceJson.getJSONObject("settings");
|
||||
if (sourceJson.has("amenities")) {
|
||||
JSONArray amenitiesArr = sourceJson.getJSONArray("amenities");
|
||||
List<Amenity> amenities = new ArrayList<>();
|
||||
for (int i = 0; i < amenitiesArr.length(); i++) {
|
||||
JSONObject amenityObj = amenitiesArr.getJSONObject(i);
|
||||
amenities.add(Amenity.parseJSON(amenityObj));
|
||||
}
|
||||
reader.amenities = amenities;
|
||||
}
|
||||
if (sourceJson.has("cities")) {
|
||||
JSONArray citiesArr = sourceJson.getJSONArray("cities");
|
||||
List<City> cities = new ArrayList<>();
|
||||
List<City> initCities = new ArrayList<>();
|
||||
List<City> matchedCities = new ArrayList<>();
|
||||
List<City> streetCities = new ArrayList<>();
|
||||
for (int i = 0; i < citiesArr.length(); i++) {
|
||||
JSONObject cityObj = citiesArr.getJSONObject(i);
|
||||
final City city = City.parseJSON(cityObj);
|
||||
cities.add(city);
|
||||
if (cityObj.has("init")) {
|
||||
initCities.add(city);
|
||||
}
|
||||
if (cityObj.has("matchCity")) {
|
||||
matchedCities.add(city);
|
||||
}
|
||||
if (cityObj.has("matchStreet")) {
|
||||
streetCities.add(city);
|
||||
}
|
||||
}
|
||||
reader.cities = cities;
|
||||
reader.initCities = initCities;
|
||||
reader.matchedCities = matchedCities;
|
||||
reader.streetCities = streetCities;
|
||||
}
|
||||
List<String> results = new ArrayList<>();
|
||||
if (sourceJson.has("results")) {
|
||||
JSONArray resultsArr = sourceJson.getJSONArray("results");
|
||||
for (int i = 0; i < resultsArr.length(); i++) {
|
||||
results.add(resultsArr.getString(i));
|
||||
}
|
||||
}
|
||||
if (TEST_EXTRA_RESULTS && sourceJson.has("extra-results")) {
|
||||
JSONArray resultsArr = sourceJson.getJSONArray("extra-results");
|
||||
for (int i = 0; i < resultsArr.length(); i++) {
|
||||
results.add(resultsArr.getString(i));
|
||||
}
|
||||
}
|
||||
|
||||
SearchSettings s = SearchSettings.parseJSON(settingsJson);
|
||||
s.setOfflineIndexes(Collections.singletonList(reader));
|
||||
|
||||
SearchPhrase phrase = new SearchPhrase(s, OsmAndCollator.primaryCollator());
|
||||
phrase = phrase.generateNewPhrase(phraseText, s);
|
||||
|
||||
final SearchUICore core = new SearchUICore(MapPoiTypes.getDefault(), "en", false);
|
||||
core.init();
|
||||
|
||||
ResultMatcher<SearchResult> rm = new ResultMatcher<SearchResult>() {
|
||||
@Override
|
||||
public boolean publish(SearchResult object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
SearchResultMatcher matcher = new SearchResultMatcher(rm, phrase, 1, new AtomicInteger(1), -1);
|
||||
core.searchInternal(phrase, matcher);
|
||||
|
||||
SearchResultCollection collection = new SearchResultCollection(phrase);
|
||||
collection.addSearchResults(matcher.getRequestResults(), true, true);
|
||||
List<SearchResult> searchResults = collection.getCurrentSearchResults();
|
||||
int i = 0;
|
||||
for (SearchResult result : searchResults) {
|
||||
String expected = results.get(i++);
|
||||
String present = result.toString();
|
||||
if (!Algorithms.stringsEqual(expected, present)) {
|
||||
System.out.println(String.format("Mismatch for '%s' != '%s' (%d, %.3f, %s). Result: ", expected,
|
||||
present, result.getFoundWordCount(), result.getUnknownPhraseMatchWeight(), result.objectType.toString()));
|
||||
for (SearchResult r : searchResults) {
|
||||
// System.out.println(String.format("\t\"%s\",", r.toString()));
|
||||
System.out.println(String.format("\"%s\", (%d, %.3f, %s),", r.toString(),
|
||||
r.getFoundWordCount(), r.getUnknownPhraseMatchWeight(), r.objectType.toString()));
|
||||
}
|
||||
}
|
||||
Assert.assertEquals(expected, present);
|
||||
if (i >= results.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class TestSearchTranslator implements MapPoiTypes.PoiTranslator {
|
||||
|
||||
private Map<String, String> enPhrases;
|
||||
private Map<String, String> phrases;
|
||||
public TestSearchTranslator(Map<String, String> phrases, Map<String, String> enPhrases) {
|
||||
this.phrases = phrases;
|
||||
this.enPhrases = enPhrases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslation(AbstractPoiType type) {
|
||||
|
@ -125,196 +271,7 @@ public class SearchCoreUITest {
|
|||
}
|
||||
return val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicates() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, true, true);
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoResort() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(2));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoResortDuplicate() throws IOException {
|
||||
SearchSettings ss = new SearchSettings((SearchSettings)null);
|
||||
ss = ss.setOriginalLocation(new LatLon(0, 0));
|
||||
SearchPhrase phrase = new SearchPhrase(ss, OsmAndCollator.primaryCollator());
|
||||
SearchResultCollection cll = new SearchUICore.SearchResultCollection(phrase);
|
||||
List<SearchResult> rs = new ArrayList<>();
|
||||
SearchResult a1 = searchResult(rs, phrase, "a", 100);
|
||||
SearchResult b2 = searchResult(rs, phrase, "b", 200);
|
||||
SearchResult b1 = searchResult(rs, phrase, "b", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
/*SearchResult a3 = */ searchResult(rs, phrase, "a", 100);
|
||||
cll.addSearchResults(rs, false, true);
|
||||
rs.clear();
|
||||
|
||||
Assert.assertEquals(3, cll.getCurrentSearchResults().size());
|
||||
Assert.assertSame(a1, cll.getCurrentSearchResults().get(0));
|
||||
Assert.assertSame(b1, cll.getCurrentSearchResults().get(1));
|
||||
Assert.assertSame(b2, cll.getCurrentSearchResults().get(2));
|
||||
|
||||
|
||||
}
|
||||
|
||||
private SearchResult searchResult(List<SearchResult> rs, SearchPhrase phrase, String text, int dist) {
|
||||
SearchResult res = new SearchResult(phrase);
|
||||
res.localeName = text;
|
||||
double d1 = MapUtils.getDistance(0, 0, 0, 1);
|
||||
res.location = new LatLon(0, dist / d1);
|
||||
rs.add(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchJsons() throws IOException {
|
||||
final File[] files = new File(SEARCH_RESOURCES_PATH).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String filename) {
|
||||
return filename.endsWith(".json");
|
||||
}
|
||||
});
|
||||
if (files != null) {
|
||||
for (File f : files) {
|
||||
testSearchImpl(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testSearchImpl(File jsonFile) throws IOException, JSONException {
|
||||
String sourceJsonText = Algorithms.getFileAsString(jsonFile);
|
||||
Assert.assertNotNull(sourceJsonText);
|
||||
Assert.assertTrue(sourceJsonText.length() > 0);
|
||||
|
||||
BinaryMapIndexReaderTest reader = new BinaryMapIndexReaderTest();
|
||||
JSONObject sourceJson = new JSONObject(sourceJsonText);
|
||||
String phraseText = sourceJson.getString("phrase");
|
||||
JSONObject settingsJson = sourceJson.getJSONObject("settings");
|
||||
if (sourceJson.has("amenities")) {
|
||||
JSONArray amenitiesArr = sourceJson.getJSONArray("amenities");
|
||||
List<Amenity> amenities = new ArrayList<>();
|
||||
for (int i = 0; i < amenitiesArr.length(); i++) {
|
||||
JSONObject amenityObj = amenitiesArr.getJSONObject(i);
|
||||
amenities.add(Amenity.parseJSON(amenityObj));
|
||||
}
|
||||
reader.amenities = amenities;
|
||||
}
|
||||
if (sourceJson.has("cities")) {
|
||||
JSONArray citiesArr = sourceJson.getJSONArray("cities");
|
||||
List<City> cities = new ArrayList<>();
|
||||
List<City> initCities = new ArrayList<>();
|
||||
List<City> matchedCities = new ArrayList<>();
|
||||
List<City> streetCities = new ArrayList<>();
|
||||
for (int i = 0; i < citiesArr.length(); i++) {
|
||||
JSONObject cityObj = citiesArr.getJSONObject(i);
|
||||
final City city = City.parseJSON(cityObj);
|
||||
cities.add(city);
|
||||
if (cityObj.has("init")) {
|
||||
initCities.add(city);
|
||||
}
|
||||
if (cityObj.has("matchCity")) {
|
||||
matchedCities.add(city);
|
||||
}
|
||||
if (cityObj.has("matchStreet")) {
|
||||
streetCities.add(city);
|
||||
}
|
||||
}
|
||||
reader.cities = cities;
|
||||
reader.initCities = initCities;
|
||||
reader.matchedCities = matchedCities;
|
||||
reader.streetCities = streetCities;
|
||||
}
|
||||
List<String> results = new ArrayList<>();
|
||||
if (sourceJson.has("results")) {
|
||||
JSONArray resultsArr = sourceJson.getJSONArray("results");
|
||||
for (int i = 0; i < resultsArr.length(); i++) {
|
||||
results.add(resultsArr.getString(i));
|
||||
}
|
||||
}
|
||||
|
||||
SearchSettings s = SearchSettings.parseJSON(settingsJson);
|
||||
s.setOfflineIndexes(Collections.singletonList(reader));
|
||||
|
||||
SearchPhrase phrase = new SearchPhrase(s, OsmAndCollator.primaryCollator());
|
||||
phrase = phrase.generateNewPhrase(phraseText, s);
|
||||
|
||||
final SearchUICore core = new SearchUICore(MapPoiTypes.getDefault(), "en", false);
|
||||
core.init();
|
||||
|
||||
ResultMatcher<SearchResult> rm = new ResultMatcher<SearchResult>() {
|
||||
@Override
|
||||
public boolean publish(SearchResult object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
SearchResultMatcher matcher = new SearchResultMatcher(rm, phrase, 1, new AtomicInteger(1), -1);
|
||||
core.searchInternal(phrase, matcher);
|
||||
|
||||
SearchResultCollection collection = new SearchResultCollection(phrase);
|
||||
collection.addSearchResults(matcher.getRequestResults(), true, true);
|
||||
List<SearchResult> searchResults = collection.getCurrentSearchResults();
|
||||
int i = 0;
|
||||
for (SearchResult result : searchResults) {
|
||||
String expected = results.get(i++);
|
||||
String present = result.toString();
|
||||
//System.out.println(present);
|
||||
Assert.assertEquals(expected, present);
|
||||
if (i >= results.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class BinaryMapIndexReaderTest extends BinaryMapIndexReader {
|
||||
|
6866
OsmAnd-java/src/test/resources/search/100_bridge_street.json
Normal file
6956
OsmAnd-java/src/test/resources/search/carrer_de_vic.json
Normal file
|
@ -12,17 +12,16 @@
|
|||
"phrase": "48 Free Street Portland",
|
||||
"results": [
|
||||
"48.0, <input> ",
|
||||
"48, Free Street (Downtown), Portland",
|
||||
"48, Free Street (Downtown), Portland"
|
||||
],
|
||||
"extra-results": [
|
||||
"48, Portland Street, North Berwick",
|
||||
"48, Portland Avenue, Old Orchard Beach",
|
||||
"Free Street (Downtown), Portland",
|
||||
"Free Street (Ferry Village), South Portland",
|
||||
"Portland Street",
|
||||
"Portland Street (Downtown), Portland",
|
||||
"Portland Street Pier, South Portland",
|
||||
"Portland Street, Yarmouth",
|
||||
"Portland Street, North Berwick",
|
||||
"Portland Street, Berwick",
|
||||
"Portland Street, South Berwick",
|
||||
"Portland Street, Fryeburg",
|
||||
"Portland Square, Portland"
|
||||
"Portland Street, Yarmouth"
|
||||
],
|
||||
"amenities": [
|
||||
{
|
||||
|
|
|
@ -11,7 +11,12 @@
|
|||
},
|
||||
"phrase": "Calle de las eras 5, Navacerrada",
|
||||
"results": [
|
||||
"5, Calle de las Eras (Uranización Los Corales), Navacerrada",
|
||||
"5, Calle de las Eras (Uranización Los Corales), Navacerrada"
|
||||
],
|
||||
"extra-results": [
|
||||
"Calle de las Eras (Uranización Los Corales), Navacerrada",
|
||||
"Calle del Sotillo (Uranización Los Corales), Pasaje de las Eras (Uranización Los Corales), Navacerrada",
|
||||
"Calle del Puerto de Navacerrada, Las Nieves",
|
||||
"5, Calle Navacerrada (Urb. Las Suertes), Las Suertes",
|
||||
"50, Calle de Francisco Navacerrada, Salamanca",
|
||||
"52, Calle de Francisco Navacerrada, Salamanca",
|
||||
|
@ -22,7 +27,12 @@
|
|||
"57, Calle de Francisco Navacerrada, Salamanca",
|
||||
"58, Calle de Francisco Navacerrada, Salamanca",
|
||||
"59, Calle de Francisco Navacerrada, Salamanca",
|
||||
"Calle del Puerto de Navacerrada, Las Nieves",
|
||||
"Pasaje de las Eras (Uranización Los Corales), Navacerrada",
|
||||
"Calle Barrio de las Peñas, Navacerrada",
|
||||
"Calle de las Cruces (Residencial Sanabria), Navacerrada",
|
||||
"Calle de las Escuelas, Navacerrada",
|
||||
"Calle de las Huertas (Residencial Sanabria), Navacerrada",
|
||||
"Calle de la Virgen de las Nieves, Puerto de Navacerrada",
|
||||
"Calle Puerto de Navacerrada, La Poveda",
|
||||
"Calle del Embalse de Navacerrada, Villa de Vallecas",
|
||||
"Calle del Puerto de Navacerrada, Puente de Vallecas",
|
||||
|
@ -32,21 +42,38 @@
|
|||
"Calle Puerto de Navacerrada, Roman Candelas",
|
||||
"Calle Navacerrada, Becerril de la Sierra",
|
||||
"Carretera de Collado Villalba a Navacerrada, El Baillo y las Hojarascas",
|
||||
"Calle Navacerrada (Cerceda), El Boalo",
|
||||
"Calle Navacerrada (El Pedregal), Bustarviejo",
|
||||
"Calle Navacerrada, Buitrago del Lozoya",
|
||||
"Carretera de Colmenar Viejo a Navacerrada, Becerril de la Sierra",
|
||||
"Carretera de Colmenar Viejo a Navacerrada, Manzanares el Real",
|
||||
"Carretera de Collado Villalba a Navacerrada, Dehesa Boyal",
|
||||
"Carretera de Collado Villalba a Navacerrada, Polideportivo Dehesa Boyal",
|
||||
"Carretera de Navacerrada, Jazmines",
|
||||
"Carretera de Colmenar Viejo a Navacerrada (Cerceda), El Boalo",
|
||||
"Carretera de Collado Villalba a Navacerrada, Cerca de Cascarrilla",
|
||||
"Carretera de Navacerrada, El Boalo",
|
||||
"Carretera de Collado Villalba a Navacerrada, Collado Mediano",
|
||||
"Camino de Navacerrada (Serranía de la Paloma), Collado Mediano",
|
||||
"Camino de Los Molinos a Navacerrada, Collado Mediano",
|
||||
"Carretera de Collado Villalba a Navacerrada, Navacerrada"
|
||||
"Calle de Ángel Rojas, Navacerrada",
|
||||
"Calle de los Robles (Uranización Los Corales), Navacerrada",
|
||||
"Calle de los Enebros (Uranización Los Corales), Navacerrada",
|
||||
"Calle de la Bola del Mundo (Residencial Sanabria), Navacerrada",
|
||||
"Calle de la Maliciosa (Residencial Sanabria), Navacerrada",
|
||||
"Calle de la Perdiz, Navacerrada",
|
||||
"Calle de la Magdalena, Navacerrada",
|
||||
"Calle las Jaras, Navacerrada",
|
||||
"Calle de la Audiencia, Navacerrada",
|
||||
"Calle de Prado Jerez, Navacerrada",
|
||||
"Calle de Carmen Conde (Residencial Sanabria), Navacerrada",
|
||||
"Calle de la Iglesia, Navacerrada",
|
||||
"Calle de la Tejera, Navacerrada",
|
||||
"Calle de la Encinilla, Navacerrada",
|
||||
"Calle de la Canaleja (Residencial Sanabria), Navacerrada",
|
||||
"Calle de Rafael Alvarado, Navacerrada",
|
||||
"Calle de Andrés Segovia, Navacerrada",
|
||||
"Calle de los Pradillos (Residencial Sanabria), Navacerrada",
|
||||
"Calle de Abel, Navacerrada",
|
||||
"Calle Praderas de San Sebastián, Navacerrada",
|
||||
"Calle de San Sebastián (Residencial Sanabria), Navacerrada",
|
||||
"Calle de Álvaro Iglesia, Navacerrada",
|
||||
"Calle de los Arcos, Navacerrada",
|
||||
"Calle de Peñalara, Puerto de Navacerrada",
|
||||
"Calle de la Bola del Mundo, Puerto de Navacerrada",
|
||||
"Calle de la Estación, Puerto de Navacerrada",
|
||||
"Calle Ginos, Puerto de Navacerrada",
|
||||
"Calle Vitoria, Puerto de Navacerrada",
|
||||
"Calle Dos Castillas, Puerto de Navacerrada",
|
||||
"Travesía de las Huertas, Navacerrada",
|
||||
"Vereda de las Encinillas, Navacerrada",
|
||||
"Centro Municipal de Mayores «Navacerrada»",
|
||||
],
|
||||
"amenities": [
|
||||
{
|
||||
|
|
|
@ -53,6 +53,109 @@
|
|||
"Spring Street, Liberty",
|
||||
"Spring Street (Livingston Manor), Rockland",
|
||||
"Spring Street, Livingston Manor",
|
||||
"Market Street, Cold Spring",
|
||||
"New Street, Cold Spring",
|
||||
"West Street, Cold Spring",
|
||||
"Fish Street, Cold Spring",
|
||||
"North Street, Cold Spring",
|
||||
"Rock Street, Cold Spring",
|
||||
"Stone Street, Cold Spring",
|
||||
"Wall Street, Cold Spring",
|
||||
"Cross Street, Cold Spring",
|
||||
"Main Street, Cold Spring",
|
||||
"Chestnut Street, Cold Spring",
|
||||
"Furnace Street, Cold Spring",
|
||||
"Garden Street, Cold Spring",
|
||||
"Church Street, Cold Spring",
|
||||
"Oak Street, Cold Spring",
|
||||
"Cherry Street, Cold Spring",
|
||||
"High Street, Cold Spring",
|
||||
"Academy Street, Cold Spring",
|
||||
"Haldane Street, Cold Spring",
|
||||
"West Bank Street, Cold Spring",
|
||||
"B Street, Cold Spring",
|
||||
"West Belvedere Street, Cold Spring",
|
||||
"Parrot Street, Cold Spring",
|
||||
"Bank Street, Cold Spring",
|
||||
"Orchard Street, Cold Spring",
|
||||
"East Belvedere Street, Cold Spring",
|
||||
"Pine Street, Cold Spring",
|
||||
"Parsonage Street, Cold Spring",
|
||||
"Hamilton Street, Cold Spring",
|
||||
"Fair Street, Cold Spring",
|
||||
"Cedar Street, Cold Spring",
|
||||
"Flora Street, Cold Spring Harbor",
|
||||
"West Main Street, Cold Spring Harbor",
|
||||
"Grove Street, Cold Spring Harbor",
|
||||
"Midland Street, Cold Spring Harbor",
|
||||
"Rusco Street, Cold Spring Harbor",
|
||||
"Main Street, Cold Spring Harbor",
|
||||
"Chestnut Street, Cold Spring Harbor",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Academy Street, Cold Spring",
|
||||
"Bank Street, Cold Spring",
|
||||
"B Street, Cold Spring",
|
||||
"Cedar Street, Cold Spring",
|
||||
"Cherry Street, Cold Spring",
|
||||
"Chestnut Street, Cold Spring",
|
||||
"Church Street, Cold Spring",
|
||||
"Cross Street, Cold Spring",
|
||||
"East Belvedere Street, Cold Spring",
|
||||
"Fair Street, Cold Spring",
|
||||
"Fish Street, Cold Spring",
|
||||
"Furnace Street, Cold Spring",
|
||||
"Garden Street, Cold Spring",
|
||||
"Haldane Street, Cold Spring",
|
||||
"Hamilton Street, Cold Spring",
|
||||
"High Street, Cold Spring",
|
||||
"Main Street, Cold Spring",
|
||||
"Market Street, Cold Spring",
|
||||
"New Street, Cold Spring",
|
||||
"North Street, Cold Spring",
|
||||
"Oak Street, Cold Spring",
|
||||
"Orchard Street, Cold Spring",
|
||||
"Parrot Street, Cold Spring",
|
||||
"Parsonage Street, Cold Spring",
|
||||
"Pine Street, Cold Spring",
|
||||
"Rock Street, Cold Spring",
|
||||
"Stone Street, Cold Spring",
|
||||
"Wall Street, Cold Spring",
|
||||
"West Bank Street, Cold Spring",
|
||||
"West Belvedere Street, Cold Spring",
|
||||
"West Street, Cold Spring",
|
||||
"Chestnut Street, Cold Spring Harbor",
|
||||
"Flora Street, Cold Spring Harbor",
|
||||
"Grove Street, Cold Spring Harbor",
|
||||
"Main Street, Cold Spring Harbor",
|
||||
"Midland Street, Cold Spring Harbor",
|
||||
"Rusco Street, Cold Spring Harbor",
|
||||
"Spring Street, Cold Spring Harbor",
|
||||
"West Main Street, Cold Spring Harbor",
|
||||
"Kraw Street, Spring Glen",
|
||||
"Munro Street, Cold Spring",
|
||||
"State Street, Cold Spring",
|
||||
"Spring Street Salt Shed",
|
||||
"6th Avenue & Spring Street",
|
||||
"Spring Street Park",
|
||||
"Broadway & Spring Street",
|
||||
"Broadway/Spring Street",
|
||||
"Spring Street Station (6) - Downtown",
|
||||
"Spring Street Station (6) - Uptown & The Bronx",
|
||||
"Richmond Road & Spring Street",
|
||||
"West Spring Street School",
|
||||
"Spring Street Gallery",
|
||||
"Spring Street Apartments",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
|
@ -63,7 +166,6 @@
|
|||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street",
|
||||
"Spring Street"
|
||||
],
|
||||
"amenities": [
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="share_location_as">Standort teilen als</string>
|
||||
<string name="live_now_description">Kontakte und Gruppen, die ihren Standort mit Ihnen teilen.</string>
|
||||
<string name="logout_from_osmand_telegram">Aus OsmAnd Tracker abmelden\?</string>
|
||||
<string name="shared_string_name">"Name "</string>
|
||||
<string name="shared_string_name">Name</string>
|
||||
<string name="by_distance">Nach Entfernung</string>
|
||||
<string name="by_name">Nach Namen</string>
|
||||
<string name="by_group">Nach Gruppe</string>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<string name="send_my_location">Meinen Standort senden</string>
|
||||
<string name="gps_and_location">Position</string>
|
||||
<string name="open_osmand">OsmAnd öffnen</string>
|
||||
<string name="shared_string_live">"Live "</string>
|
||||
<string name="shared_string_live">Live</string>
|
||||
<string name="get_telegram_title">Registrierung in Telegram</string>
|
||||
<string name="get_telegram_account_first">Sie benötigen ein Telegram-Konto, um die Standortfreigabe nutzen zu können.</string>
|
||||
<string name="get_telegram_description_continue">Bitte installieren Sie Telegram und richten Sie ein Konto ein.</string>
|
||||
|
@ -151,9 +151,7 @@
|
|||
<string name="start_location_sharing">Standort freigeben</string>
|
||||
<string name="location_service_no_gps_available">Wählen Sie einen der Standortanbieter aus, um Ihren Standort freizugeben.</string>
|
||||
<string name="sharing_location">Standort teilen</string>
|
||||
<string name="welcome_descr">
|
||||
<b>OsmAnd Tracker</b> ermöglicht es Ihnen, Ihren Standort zu teilen und den anderer in OsmAnd zu sehen.<br/>
|
||||
<br/>Die App verwendet die API von Telegram, also benötigen Sie ein Telegram-Konto.</string>
|
||||
<string name="welcome_descr"><b>OsmAnd Tracker</b> ermöglicht es Ihnen, Ihren Standort zu teilen und den anderer in OsmAnd zu sehen.<br/> <br/>Die App verwendet die API von Telegram, also benötigen Sie ein Telegram-Konto.</string>
|
||||
<string name="enter_another_device_name">Wählen Sie einen Namen, den Sie noch nicht benutzt haben</string>
|
||||
<string name="device_added_successfully">%1$s hinzugefügt.</string>
|
||||
<string name="shared_string_add">Hinzufügen</string>
|
||||
|
|
|
@ -216,4 +216,13 @@
|
|||
<string name="search_contacts_descr">Procura en tódolos teus grupos e contactos.</string>
|
||||
<string name="type_contact_or_group_name">Escribe o nome do contacto ou do grupo</string>
|
||||
<string name="shared_string_search">Procurar</string>
|
||||
<string name="status_widget_title">Estado do Rastrexador do OsmAnd</string>
|
||||
<string name="shared_string_suggested">Suxerido</string>
|
||||
<string name="back_to_osmand">Voltar ó OsmAnd</string>
|
||||
<string name="duration_ago">hai %1$s</string>
|
||||
<string name="last_response_duration">Última resposta: hai %1$s</string>
|
||||
<string name="last_update_from_telegram_duration">Última actualización dende o Telegram: hai %1$s</string>
|
||||
<string name="last_response_date">Última resposta: %1$s</string>
|
||||
<string name="last_update_from_telegram_date">Última actualización dende o Telegram: %1$s</string>
|
||||
<string name="shared_string_error_short">ERR</string>
|
||||
</resources>
|
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 1 KiB |
|
@ -4,7 +4,7 @@
|
|||
<item android:drawable="@color/map_background_color_light"/>
|
||||
<item android:top="@dimen/splash_screen_logo_top">
|
||||
<bitmap
|
||||
android:gravity="center_horizontal|top"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_logo_splash_osmand"/>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -4,7 +4,7 @@
|
|||
<item android:drawable="@color/map_background_color_light"/>
|
||||
<item android:top="@dimen/splash_screen_logo_top">
|
||||
<bitmap
|
||||
android:gravity="center_horizontal|top"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_logo_splash_osmand"/>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -4,7 +4,7 @@
|
|||
<item android:drawable="@color/map_background_color_light"/>
|
||||
<item android:top="@dimen/splash_screen_logo_top">
|
||||
<bitmap
|
||||
android:gravity="center_horizontal|top"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_logo_splash_osmand_plus"/>
|
||||
</item>
|
||||
</layer-list>
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
14
OsmAnd/res/drawable/ic_action_external_link.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11,3H5C3.8954,3 3,3.8954 3,5V19C3,20.1046 3.8954,21 5,21H19C20.1046,21 21,20.1046 21,19V13H19V19H5V5H11V3Z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M13.0001,3H21.0001V11H19.0001V6.4142L11.7072,13.7071L10.293,12.2929L17.5859,5H13.0001V3Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
20
OsmAnd/res/drawable/ic_action_notification_navigation.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M22,22V5C22,3.3431 20.6569,2 19,2H5C3.3431,2 2,3.3431 2,5V22H4V7H20V22H22Z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.5"/>
|
||||
<path
|
||||
android:pathData="M4,7h16v15h-16z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M20,7H4V16H20V7ZM9,10V8.58C9,8.2597 8.7403,8 8.42,8C8.1486,8 7.8858,8.0951 7.6774,8.2689L5.3841,10.1799C5.1407,10.3827 5,10.6832 5,11C5,11.3168 5.1407,11.6173 5.3841,11.8201L7.6774,13.7311C7.8858,13.9049 8.1486,14 8.42,14C8.7403,14 9,13.7403 9,13.42L9,12H10C10.5523,12 11,12.4477 11,13V14C11,14.5523 11.4477,15 12,15C12.5523,15 13,14.5523 13,14V13C13,11.3431 11.6569,10 10,10H9ZM14,11C14,10.4477 14.4477,10 15,10H18C18.5523,10 19,10.4477 19,11C19,11.5523 18.5523,12 18,12H15C14.4477,12 14,11.5523 14,11Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
19
OsmAnd/res/drawable/ic_action_power_button.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M2,2V8H16V22H19V5C19,3.3431 17.6569,2 16,2H2Z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M2,8h14v14h-14z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M19,8H19.5C19.7761,8 20,8.2239 20,8.5V15.5C20,15.7761 19.7761,16 19.5,16H19V8Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
45
OsmAnd/res/drawable/ic_actions_menu.xml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M7,19C7,20.1046 6.1046,21 5,21C3.8954,21 3,20.1046 3,19C3,17.8954 3.8954,17 5,17C6.1046,17 7,17.8954 7,19Z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.5"/>
|
||||
<path
|
||||
android:pathData="M14,19C14,20.1046 13.1046,21 12,21C10.8954,21 10,20.1046 10,19C10,17.8954 10.8954,17 12,17C13.1046,17 14,17.8954 14,19Z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.5"/>
|
||||
<path
|
||||
android:pathData="M19,21C20.1046,21 21,20.1046 21,19C21,17.8954 20.1046,17 19,17C17.8954,17 17,17.8954 17,19C17,20.1046 17.8954,21 19,21Z"
|
||||
android:strokeAlpha="0.5"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.5"/>
|
||||
<path
|
||||
android:pathData="M7,12C7,13.1046 6.1046,14 5,14C3.8954,14 3,13.1046 3,12C3,10.8954 3.8954,10 5,10C6.1046,10 7,10.8954 7,12Z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M14,12C14,13.1046 13.1046,14 12,14C10.8954,14 10,13.1046 10,12C10,10.8954 10.8954,10 12,10C13.1046,10 14,10.8954 14,12Z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M19,14C20.1046,14 21,13.1046 21,12C21,10.8954 20.1046,10 19,10C17.8954,10 17,10.8954 17,12C17,13.1046 17.8954,14 19,14Z"
|
||||
android:strokeAlpha="0.7"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.7"/>
|
||||
<path
|
||||
android:pathData="M7,5C7,6.1046 6.1046,7 5,7C3.8954,7 3,6.1046 3,5C3,3.8954 3.8954,3 5,3C6.1046,3 7,3.8954 7,5Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M14,5C14,6.1046 13.1046,7 12,7C10.8954,7 10,6.1046 10,5C10,3.8954 10.8954,3 12,3C13.1046,3 14,3.8954 14,5Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M19,7C20.1046,7 21,6.1046 21,5C21,3.8954 20.1046,3 19,3C17.8954,3 17,3.8954 17,5C17,6.1046 17.8954,7 19,7Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
13
OsmAnd/res/drawable/ic_compass.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,23L6,12H8.2782L12,18.8233L15.7218,12H18L12,23Z"
|
||||
android:fillColor="#505050"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M18,12L12,1L6,12H18Z"
|
||||
android:fillColor="#E53935"/>
|
||||
</vector>
|
12
OsmAnd/res/drawable/ic_compass_bearing.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4.1161,21.9676L12,19.7647L19.8839,21.9676C19.9609,21.9891 20.0406,22 20.1206,22H20.1832C20.6343,22 21,21.6343 21,21.1832C21,21.0626 20.9733,20.9434 20.9218,20.8344L12.7135,3.4521C12.5832,3.1761 12.3053,3 12,3C11.6947,3 11.4168,3.1761 11.2865,3.4521L3.0782,20.8344C3.0267,20.9434 3,21.0626 3,21.1832C3,21.6343 3.3657,22 3.8168,22H3.8795C3.9594,22 4.0391,21.9891 4.1161,21.9676Z"
|
||||
android:fillColor="#536DFE"/>
|
||||
<path
|
||||
android:pathData="M10,17V11H11L13,15V11H14V17H13L11,13V17H10Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
12
OsmAnd/res/drawable/ic_compass_bearing_white.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4.1161,21.9676L12,19.7647L19.8839,21.9676C19.9609,21.9891 20.0406,22 20.1206,22H20.1832C20.6343,22 21,21.6343 21,21.1832C21,21.0626 20.9733,20.9434 20.9218,20.8344L12.7135,3.4521C12.5832,3.1761 12.3053,3 12,3C11.6947,3 11.4168,3.1761 11.2865,3.4521L3.0782,20.8344C3.0267,20.9434 3,21.0626 3,21.1832C3,21.6343 3.3657,22 3.8168,22H3.8795C3.9594,22 4.0391,21.9891 4.1161,21.9676Z"
|
||||
android:fillColor="#536DFE"/>
|
||||
<path
|
||||
android:pathData="M10,17V11H11L13,15V11H14V17H13L11,13V17H10Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
12
OsmAnd/res/drawable/ic_compass_niu.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16,10L12,3L8,10H16Z"
|
||||
android:fillColor="#E53935"/>
|
||||
<path
|
||||
android:pathData="M8,21V12H10L14,18V12H16V21H14L10,15V21H8Z"
|
||||
android:fillColor="#505050"/>
|
||||
</vector>
|
12
OsmAnd/res/drawable/ic_compass_niu_white.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16,10L12,3L8,10H16Z"
|
||||
android:fillColor="#E53935"/>
|
||||
<path
|
||||
android:pathData="M8,21V12H10L14,18V12H16V21H14L10,15V21H8Z"
|
||||
android:fillColor="#CCCCCC"/>
|
||||
</vector>
|
13
OsmAnd/res/drawable/ic_compass_white.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,23L6,12H8.2782L12,18.8233L15.7218,12H18L12,23Z"
|
||||
android:fillColor="#CCCCCC"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M18,12L12,1L6,12H18Z"
|
||||
android:fillColor="#E53935"/>
|
||||
</vector>
|
|
@ -5,6 +5,6 @@
|
|||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M5,3C3.8954,3 3,3.8954 3,5V19C3,20.1046 3.8954,21 5,21H19C20.1046,21 21,20.1046 21,19V5C21,3.8954 20.1046,3 19,3H5ZM19,5H5V19H19V5ZM7,7H11V11H7V7ZM17,7H13V11H17V7ZM7,13H11V17H7V13ZM17,13H13V17H17V13Z"
|
||||
android:fillColor="#727272"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -5,5 +5,5 @@
|
|||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M13,2H11V11H2V13H11V22H13V13H22V11H13V2Z"
|
||||
android:fillColor="#727272"/>
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
|
@ -5,5 +5,5 @@
|
|||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M22,11l-0,2l-20,0l-0,-2z"
|
||||
android:fillColor="#727272"/>
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
25
OsmAnd/res/drawable/widget_fps_day.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M2,19L22,19V21C22,22.1046 21.1046,23 20,23H4C2.8954,23 2,22.1046 2,21V19Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.3"/>
|
||||
<path
|
||||
android:pathData="M2,4C2,2.8954 2.8954,2 4,2H20C21.1046,2 22,2.8954 22,4V20C22,21.1046 21.1046,22 20,22H4C2.8954,22 2,21.1046 2,20V4Z"
|
||||
android:fillColor="#59361B"/>
|
||||
<path
|
||||
android:pathData="M4,4H20V20H4V4Z"
|
||||
android:fillColor="#FFC107"/>
|
||||
<path
|
||||
android:pathData="M6,10H9V11H7V12H9V13H7V15H6V12.5V10ZM10,10H12.5C13.3284,10 14,10.6716 14,11.5C14,12.3284 13.3284,13 12.5,13H11V15H10V12.5V10ZM11,12H12.5C12.7761,12 13,11.7761 13,11.5C13,11.2239 12.7761,11 12.5,11H11V12ZM16,10C15.4477,10 15,10.4477 15,11V12C15,12.5523 15.4477,13 16,13H17V14H15V15H17C17.5523,15 18,14.5523 18,14V13C18,12.4477 17.5523,12 17,12H16V11H18V10H16Z"
|
||||
android:fillColor="#ffffff"
|
||||
android:fillAlpha="0.3"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M6,9H6.5H9V10H7V11H9V12H7V14H6V11.5V9.5V9ZM10,9H10.5H12.5C13.3284,9 14,9.6716 14,10.5C14,11.3284 13.3284,12 12.5,12H11V14H10V11.5V9.5V9ZM11,11H12.5C12.7761,11 13,10.7761 13,10.5C13,10.2239 12.7761,10 12.5,10H11V11ZM16,9C15.4477,9 15,9.4477 15,10V11C15,11.5523 15.4477,12 16,12H17V13H15V14H17C17.5523,14 18,13.5523 18,13V12C18,11.4477 17.5523,11 17,11H16V10H18V9H16Z"
|
||||
android:fillColor="#59361B"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
25
OsmAnd/res/drawable/widget_fps_night.xml
Normal file
|
@ -0,0 +1,25 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M2,19L22,19V21C22,22.1046 21.1046,23 20,23H4C2.8954,23 2,22.1046 2,21V19Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.3"/>
|
||||
<path
|
||||
android:pathData="M2,4C2,2.8954 2.8954,2 4,2H20C21.1046,2 22,2.8954 22,4V20C22,21.1046 21.1046,22 20,22H4C2.8954,22 2,21.1046 2,20V4Z"
|
||||
android:fillColor="#FFC107"/>
|
||||
<path
|
||||
android:pathData="M4,4H20V20H4V4Z"
|
||||
android:fillColor="#59361B"/>
|
||||
<path
|
||||
android:pathData="M6,10H9V11H7V12H9V13H7V15H6V12.5V10ZM10,10H12.5C13.3284,10 14,10.6716 14,11.5C14,12.3284 13.3284,13 12.5,13H11V15H10V12.5V10ZM11,12H12.5C12.7761,12 13,11.7761 13,11.5C13,11.2239 12.7761,11 12.5,11H11V12ZM16,10C15.4477,10 15,10.4477 15,11V12C15,12.5523 15.4477,13 16,13H17V14H15V15H17C17.5523,15 18,14.5523 18,14V13C18,12.4477 17.5523,12 17,12H16V11H18V10H16Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.3"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M6,9H6.5H9V10H7V11H9V12H7V14H6V11.5V9.5V9ZM10,9H10.5H12.5C13.3284,9 14,9.6716 14,10.5C14,11.3284 13.3284,12 12.5,12H11V14H10V11.5V9.5V9ZM11,11H12.5C12.7761,11 13,10.7761 13,10.5C13,10.2239 12.7761,10 12.5,10H11V11ZM16,9C15.4477,9 15,9.4477 15,10V11C15,11.5523 15.4477,12 16,12H17V13H15V14H17C17.5523,14 18,13.5523 18,13V12C18,11.4477 17.5523,11 17,11H16V10H18V9H16Z"
|
||||
android:fillColor="#FFC107"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -7,8 +7,9 @@
|
|||
android:layout_width="fill_parent"
|
||||
android:layout_height="@dimen/dashboard_map_toolbar"
|
||||
android:background="@color/app_bar_color_light"
|
||||
app:contentInsetLeft="4dp"
|
||||
app:contentInsetStart="4dp"
|
||||
android:padding="0dp"
|
||||
app:contentInsetLeft="0dp"
|
||||
app:contentInsetStart="0dp"
|
||||
app:contentInsetRight="0dp"
|
||||
app:contentInsetEnd="0dp">
|
||||
|
||||
|
@ -25,15 +26,16 @@
|
|||
android:gravity="start"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
<ImageButton
|
||||
android:id="@+id/toolbar_back"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/acceptable_touch_radius"
|
||||
android:layout_height="@dimen/acceptable_touch_radius"
|
||||
android:layout_marginStart="@dimen/list_item_button_padding"
|
||||
android:layout_marginLeft="@dimen/list_item_button_padding"
|
||||
android:layout_marginEnd="@dimen/list_item_button_padding"
|
||||
android:layout_marginRight="@dimen/list_item_button_padding"
|
||||
android:contentDescription="@string/back_to_map"
|
||||
android:layout_marginLeft="@dimen/multi_selection_menu_padding_top"
|
||||
android:layout_marginRight="@dimen/multi_selection_menu_padding_top"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/dashboard_button_light"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_arrow_back"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
@ -53,6 +55,7 @@
|
|||
android:id="@+id/toolbar_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:scaleType="center"
|
||||
android:textColor="@color/abc_primary_text_material_dark"
|
||||
android:textSize="@dimen/abc_text_size_large_material"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/list_content_padding"
|
||||
android:layout_marginRight="@dimen/list_content_padding"
|
||||
osmand:srcCompat="@drawable/map_favorite" />
|
||||
osmand:srcCompat="@drawable/ic_action_favorite" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="@dimen/dashboard_map_toolbar"
|
||||
android:padding="0dp"
|
||||
app:contentInsetLeft="54dp"
|
||||
app:contentInsetStart="54dp"
|
||||
app:contentInsetRight="0dp"
|
||||
|
|