diff --git a/OsmAnd-java/src/main/java/net/osmand/CollatorStringMatcher.java b/OsmAnd-java/src/main/java/net/osmand/CollatorStringMatcher.java
index 27390f3760..d6011c6209 100644
--- a/OsmAnd-java/src/main/java/net/osmand/CollatorStringMatcher.java
+++ b/OsmAnd-java/src/main/java/net/osmand/CollatorStringMatcher.java
@@ -22,7 +22,8 @@ public class CollatorStringMatcher implements StringMatcher {
CHECK_STARTS_FROM_SPACE_NOT_BEGINNING,
CHECK_EQUALS_FROM_SPACE,
CHECK_CONTAINS,
- CHECK_ONLY_STARTS_WITH_TRIM
+ CHECK_ONLY_STARTS_WITH_TRIM,
+ CHECK_EQUALS,
}
public CollatorStringMatcher(String part, StringMatcherMode mode) {
@@ -55,6 +56,8 @@ public class CollatorStringMatcher implements StringMatcher {
return cstartsWith(collator, base, part, true, false, false, false);
case CHECK_ONLY_STARTS_WITH_TRIM:
return cstartsWith(collator, base, part, true, false, false, true);
+ case CHECK_EQUALS:
+ return cstartsWith(collator, base, part, false, false, true, false);
}
return false;
}
@@ -160,6 +163,9 @@ public class CollatorStringMatcher implements StringMatcher {
}
}
}
+ if (!checkBeginning && !checkSpaces && equals) {
+ return collator.equals(searchIn, theStart);
+ }
return false;
}
diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/CommonWords.java b/OsmAnd-java/src/main/java/net/osmand/binary/CommonWords.java
index b713b8a14d..bee5cb6639 100644
--- a/OsmAnd-java/src/main/java/net/osmand/binary/CommonWords.java
+++ b/OsmAnd-java/src/main/java/net/osmand/binary/CommonWords.java
@@ -5,10 +5,13 @@ import java.util.Map;
public class CommonWords {
private static Map commonWordsDictionary = new LinkedHashMap<>();
+ private static Map frequentlyUsedWordsDictionary = new LinkedHashMap<>();
private static void addCommon(String string) {
commonWordsDictionary.put(string, commonWordsDictionary.size());
}
-
+ private static void addFrequentlyUsed(String string) {
+ frequentlyUsedWordsDictionary.put(string, frequentlyUsedWordsDictionary.size());
+ }
public static int getCommon(String name) {
// if(true) {
// // not ready for old versions yet
@@ -17,10 +20,15 @@ public class CommonWords {
Integer i = commonWordsDictionary.get(name);
return i == null ? -1 : i.intValue();
}
-
+
+ public static int getFrequentlyUsed(String name) {
+ Integer i = frequentlyUsedWordsDictionary.get(name);
+ return i == null ? -1 : i.intValue();
+ }
+
public static int getCommonSearch(String name) {
Integer i = commonWordsDictionary.get(name);
- return i == null ? -1 : i.intValue();
+ return i == null ? getFrequentlyUsed(name) : i.intValue();
}
public static int getCommonGeocoding(String name) {
@@ -29,6 +37,8 @@ public class CommonWords {
}
static {
+ addFrequentlyUsed("santa");
+
addCommon("la");
addCommon("via");
addCommon("rua");
diff --git a/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java b/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java
index 126b230a2c..5e3a62c05d 100644
--- a/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java
+++ b/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java
@@ -514,7 +514,8 @@ public class SearchUICore {
public boolean isSearchMoreAvailable(SearchPhrase phrase) {
for (SearchCoreAPI api : apis) {
- if (api.getSearchPriority(phrase) >= 0 && api.isSearchMoreAvailable(phrase)) {
+ if (api.isSearchAvailable(phrase) && api.getSearchPriority(phrase) >= 0
+ && api.isSearchMoreAvailable(phrase)) {
return true;
}
}
diff --git a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java
index 13ee16ab5b..9c3c54c803 100644
--- a/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java
+++ b/OsmAnd-java/src/main/java/net/osmand/search/core/SearchCoreFactory.java
@@ -317,6 +317,11 @@ public class SearchCoreFactory {
&& phrase.isSearchTypeAllowed(ObjectType.CITY)) {
String wrd = phrase.getUnknownWordToSearch();
NameStringMatcher nm = phrase.getNameStringMatcher(wrd, phrase.isUnknownSearchWordComplete());
+ String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
+ NameStringMatcher phraseMatcher = null;
+ if (!Algorithms.isEmpty(unknownSearchPhrase)) {
+ phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
+ }
// NameStringMatcher nm = phrase.getNameStringMatcher();
resArray.clear();
resArray = townCitiesQR.queryInBox(bbox, resArray);
@@ -337,6 +342,9 @@ public class SearchCoreFactory {
resultMatcher.publish(res);
} else if (nm.matches(res.localeName) || nm.matches(res.otherNames)) {
res.firstUnknownWordMatches = wrd.equals(phrase.getUnknownSearchWord());
+ if (phraseMatcher != null) {
+ res.unknownPhraseMatches = phraseMatcher.matches(res.localeName) || phraseMatcher.matches(res.otherNames);
+ }
subSearchApiOrPublish(phrase, resultMatcher, res, cityApi);
}
if (limit++ > LIMIT * phrase.getRadiusLevel()) {
@@ -464,6 +472,11 @@ public class SearchCoreFactory {
SearchPhraseDataType.ADDRESS);
String wordToSearch = phrase.getUnknownWordToSearch();
+ String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
+ NameStringMatcher phraseMatcher = null;
+ if (!Algorithms.isEmpty(unknownSearchPhrase)) {
+ phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
+ }
while (offlineIterator.hasNext() && wordToSearch.length() > 0) {
BinaryMapIndexReader r = offlineIterator.next();
currentFile[0] = r;
@@ -478,6 +491,9 @@ public class SearchCoreFactory {
r.searchAddressDataByName(req);
for (SearchResult res : immediateResults) {
res.firstUnknownWordMatches = wordToSearch.equals(phrase.getUnknownSearchWord());
+ if (phraseMatcher != null) {
+ res.unknownPhraseMatches = phraseMatcher.matches(res.localeName) || phraseMatcher.matches(res.otherNames);
+ }
if (res.objectType == ObjectType.STREET) {
City ct = ((Street) res.object).getCity();
phrase.countUnknownWordsMatch(res,
@@ -520,19 +536,15 @@ public class SearchCoreFactory {
final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1];
Iterator offlineIterator = phrase.getRadiusOfflineIndexes(BBOX_RADIUS,
SearchPhraseDataType.POI);
- String searchWord = phrase.getUnknownSearchWord();
- if (searchWord.length() < FIRST_WORD_MIN_LENGTH && phrase.getUnknownSearchWords().size() > 0) {
- for (String unknownSearchWord : phrase.getUnknownSearchWords()) {
- if (unknownSearchWord.length() >= FIRST_WORD_MIN_LENGTH) {
- searchWord = unknownSearchWord;
- break;
- }
- }
- }
- if (searchWord.length() < FIRST_WORD_MIN_LENGTH) {
- return false;
- }
+ String searchWord = phrase.getUnknownWordToSearch();
final NameStringMatcher nm = phrase.getNameStringMatcher(searchWord, phrase.isUnknownSearchWordComplete());
+ String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
+ final NameStringMatcher phraseMatcher;
+ if (!Algorithms.isEmpty(unknownSearchPhrase)) {
+ phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
+ } else {
+ phraseMatcher = null;
+ }
QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE);
final Set ids = new HashSet();
SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest(
@@ -574,6 +586,9 @@ public class SearchCoreFactory {
sr.priorityDistance = 1;
}
sr.priority = SEARCH_AMENITY_BY_NAME_PRIORITY;
+ if (phraseMatcher != null) {
+ sr.unknownPhraseMatches = phraseMatcher.matches(sr.localeName) || phraseMatcher.matches(sr.otherNames);
+ }
phrase.countUnknownWordsMatch(sr);
sr.objectType = ObjectType.POI;
resultMatcher.publish(sr);
@@ -606,9 +621,7 @@ public class SearchCoreFactory {
if (p.hasObjectType(ObjectType.POI_TYPE)) {
return -1;
}
- if (p.getUnknownSearchWordLength() >= FIRST_WORD_MIN_LENGTH
- || p.getUnknownSearchWords().size() > 0
- || p.getRadiusLevel() > 1) {
+ if (p.getUnknownWordToSearch().length() >= FIRST_WORD_MIN_LENGTH || p.getRadiusLevel() > 1) {
return SEARCH_AMENITY_BY_NAME_API_PRIORITY_IF_3_CHAR;
}
return -1;
@@ -878,6 +891,13 @@ public class SearchCoreFactory {
private ResultMatcher getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
final String customName, final BinaryMapIndexReader selected,
final Set searchedPois) {
+ String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
+ final NameStringMatcher phraseMatcher;
+ if (!Algorithms.isEmpty(unknownSearchPhrase)) {
+ phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
+ } else {
+ phraseMatcher = null;
+ }
final NameStringMatcher ns;
final boolean hasCustomName = !Algorithms.isEmpty(customName);
if (hasCustomName) {
@@ -918,6 +938,9 @@ public class SearchCoreFactory {
res.location = object.getLocation();
res.priority = SEARCH_AMENITY_BY_TYPE_PRIORITY;
res.priorityDistance = 1;
+ if (phraseMatcher != null) {
+ res.unknownPhraseMatches = phraseMatcher.matches(res.localeName) || phraseMatcher.matches(res.otherNames);
+ }
res.objectType = ObjectType.POI;
resultMatcher.publish(res);
return false;
@@ -975,6 +998,7 @@ public class SearchCoreFactory {
public static class SearchStreetByCityAPI extends SearchBaseAPI {
+ private static final int DEFAULT_ADDRESS_BBOX_RADIUS = 100 * 1000;
private SearchBaseAPI streetsAPI;
public SearchStreetByCityAPI(SearchBuildingAndIntersectionsByStreetAPI streetsAPI) {
@@ -988,6 +1012,16 @@ public class SearchCoreFactory {
return phrase.getRadiusLevel() == 1 && getSearchPriority(phrase) != -1;
}
+ @Override
+ public int getMinimalSearchRadius(SearchPhrase phrase) {
+ return phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS);
+ }
+
+ @Override
+ public int getNextSearchRadius(SearchPhrase phrase) {
+ return phrase.getNextRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS);
+ }
+
private static int LIMIT = 10000;
@Override
public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException {
@@ -1001,6 +1035,11 @@ public class SearchCoreFactory {
String wordToSearch = phrase.getUnknownWordToSearch();
boolean firstUnknownWordMatches = wordToSearch.equals(phrase.getUnknownSearchWord());
NameStringMatcher nm = phrase.getNameStringMatcher(wordToSearch, phrase.isUnknownSearchWordComplete());
+ String unknownSearchPhrase = phrase.getUnknownSearchPhrase().trim();
+ NameStringMatcher phraseMatcher = null;
+ if (!Algorithms.isEmpty(unknownSearchPhrase)) {
+ phraseMatcher = new NameStringMatcher(unknownSearchPhrase, StringMatcherMode.CHECK_EQUALS);
+ }
for (Street object : c.getStreets()) {
SearchResult res = new SearchResult(phrase);
@@ -1018,6 +1057,9 @@ public class SearchCoreFactory {
res.firstUnknownWordMatches = firstUnknownWordMatches ||
phrase.getNameStringMatcher().matches(res.localeName) ||
phrase.getNameStringMatcher().matches(res.otherNames);
+ if (phraseMatcher != null) {
+ res.unknownPhraseMatches = phraseMatcher.matches(res.localeName) || phraseMatcher.matches(res.otherNames);
+ }
res.localeRelatedObjectName = c.getName(phrase.getSettings().getLang(), phrase.getSettings().isTransliterate());
res.object = object;
res.preferredZoom = 17;
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 c2f214624e..884ea96b7c 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
@@ -33,6 +33,7 @@ public class SearchPhrase {
private List unknownWords = new ArrayList<>();
private List unknownWordsMatcher = new ArrayList<>();
private String unknownSearchWordTrim;
+ private String rawUnknownSearchPhrase = "";
private String unknownSearchPhrase = "";
private AbstractPoiType unknownSearchWordPoiType;
@@ -145,6 +146,7 @@ public class SearchPhrase {
break;
}
}
+ sp.rawUnknownSearchPhrase = text;
sp.unknownSearchPhrase = restText;
sp.unknownWords.clear();
sp.unknownWordsMatcher.clear();
@@ -213,7 +215,11 @@ public class SearchPhrase {
public String getUnknownSearchWord() {
return unknownSearchWordTrim;
}
-
+
+ public String getRawUnknownSearchPhrase() {
+ return rawUnknownSearchPhrase;
+ }
+
public String getUnknownSearchPhrase() {
return unknownSearchPhrase;
}
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 3bf7cfa995..03294e6e8a 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
@@ -20,7 +20,7 @@ public class SearchResult {
public SearchResult parentSearchResult;
public Collection otherWordsMatch = null;
public boolean firstUnknownWordMatches = true;
-
+ public boolean unknownPhraseMatches = false;
public SearchResult(SearchPhrase sp) {
@@ -32,6 +32,9 @@ public class SearchResult {
if(firstUnknownWordMatches) {
inc = 1;
}
+ if (unknownPhraseMatches) {
+ inc += 1000;
+ }
if(otherWordsMatch != null) {
inc += otherWordsMatch.size();
}
diff --git a/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java b/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java
index d9d8356d1c..6f434f3dcc 100644
--- a/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java
+++ b/OsmAnd-java/src/main/java/net/osmand/util/OpeningHoursParser.java
@@ -636,6 +636,7 @@ public class OpeningHoursParser {
* Day number 0 is MONDAY
*/
private boolean[] days = new boolean[7];
+ private boolean hasDays = false;
/**
* represents the list on which month it is open.
@@ -646,7 +647,8 @@ public class OpeningHoursParser {
/**
* represents the list on which day it is open.
*/
- private boolean[] dayMonths = new boolean[31];
+ private boolean[][] dayMonths = new boolean[12][31];
+ private boolean hasDayMonths = false;
/**
* lists of equal size representing the start and end times
@@ -694,10 +696,14 @@ public class OpeningHoursParser {
/**
* @return the day months of the rule
*/
- public boolean[] getDayMonths() {
+ public boolean[][] getDayMonths() {
return dayMonths;
}
+ public boolean[] getDayMonths(int month) {
+ return dayMonths[month];
+ }
+
/**
* return an array representing the months of the rule
*
@@ -982,20 +988,108 @@ public class OpeningHoursParser {
break;
}
}
- // Month
- if (!allMonths) {
+ boolean allDays = !hasDayMonths;
+ if (!allDays) {
+ boolean dash = false;
+ boolean first = true;
+ int monthAdded = -1;
+ int excludedMonthEnd = -1;
+ int excludedDayEnd = -1;
+ int excludedMonthStart = -1;
+ int excludedDayStart = -1;
+ if (dayMonths[0][0] && dayMonths[11][30]) {
+ int prevMonth = 0;
+ int prevDay = 0;
+ for (int month = 0; month < dayMonths.length; month++) {
+ for (int day = 0; day < dayMonths[month].length; day++) {
+ if (day == 1) {
+ prevMonth = month;
+ }
+ if (!dayMonths[month][day]) {
+ excludedMonthEnd = prevMonth;
+ excludedDayEnd = prevDay;
+ break;
+ }
+ prevDay = day;
+ }
+ if (excludedDayEnd != -1) {
+ break;
+ }
+ }
+ prevMonth = dayMonths.length - 1;
+ prevDay = dayMonths[prevMonth].length - 1;
+ for (int month = dayMonths.length - 1; month >= 0; month--) {
+ for (int day = dayMonths[month].length - 1; day >= 0; day--) {
+ if (day == dayMonths[month].length - 2) {
+ prevMonth = month;
+ }
+ if (!dayMonths[month][day]) {
+ excludedMonthStart = prevMonth;
+ excludedDayStart = prevDay;
+ break;
+ }
+ prevDay = day;
+ }
+ if (excludedDayStart != -1) {
+ break;
+ }
+ }
+ }
+ for (int month = 0; month < dayMonths.length; month++) {
+ for (int day = 0; day < dayMonths[month].length; day++) {
+ if (excludedDayStart != -1 && excludedDayEnd != -1) {
+ if (month < excludedMonthEnd || (month == excludedMonthEnd && day <= excludedDayEnd)) {
+ continue;
+ } else if (month > excludedMonthStart || (month == excludedMonthStart && day >= excludedDayStart)) {
+ continue;
+ }
+ }
+ if (dayMonths[month][day]) {
+ if (day == 0 && dash) {
+ continue;
+ }
+ if (day > 0 && dayMonths[month][day - 1]
+ && ((day < dayMonths[month].length - 1 && dayMonths[month][day + 1]) || (day == dayMonths[month].length - 1 && month < dayMonths.length - 1 && dayMonths[month + 1][0]))) {
+ if (!dash) {
+ dash = true;
+ if (!first) {
+ b.append("-");
+ }
+ }
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else if (!dash) {
+ b.append(", ");
+ monthAdded = -1;
+ }
+ if (monthAdded != month) {
+ b.append(monthNames[month]).append(" ");
+ monthAdded = month;
+ }
+ b.append(day + 1);
+ dash = false;
+ }
+ }
+ }
+ if (excludedDayStart != -1 && excludedDayEnd != -1) {
+ if (first) {
+ first = false;
+ } else if (!dash) {
+ b.append(", ");
+ }
+ b.append(monthNames[excludedMonthStart]).append(" ").append(excludedDayStart + 1)
+ .append("-")
+ .append(monthNames[excludedMonthEnd]).append(" ").append(excludedDayEnd + 1);
+ }
+ if (!first) {
+ b.append(" ");
+ }
+ } else if (!allMonths) {
addArray(months, monthNames, b);
}
- boolean allDays = true;
- for (int i = 0; i < dayMonths.length; i++) {
- if (!dayMonths[i]) {
- allDays = false;
- break;
- }
- }
- if (!allDays) {
- addArray(dayMonths, null, b);
- }
+
// Day
appendDaysString(b, dayNames);
// Time
@@ -1312,9 +1406,21 @@ public class OpeningHoursParser {
int i = cal.get(Calendar.DAY_OF_WEEK);
int day = (i + 5) % 7;
int previous = (day + 6) % 7;
- boolean thisDay = days[day] || dayMonths[dmonth];
+ boolean thisDay = hasDays || hasDayMonths;
+ if (thisDay && hasDayMonths) {
+ thisDay = dayMonths[month][dmonth];
+ }
+ if (thisDay && hasDays) {
+ thisDay = days[day];
+ }
// potential error for Dec 31 12:00-01:00
- boolean previousDay = days[previous] || (dmonth > 0 && dayMonths[dmonth - 1]);
+ boolean previousDay = hasDays || hasDayMonths;
+ if (previousDay && hasDayMonths && dmonth > 0) {
+ previousDay = dayMonths[month][dmonth - 1];
+ }
+ if (previousDay && hasDays) {
+ previousDay = days[previous];
+ }
if (!thisDay && !previousDay) {
return 0;
}
@@ -1462,13 +1568,23 @@ public class OpeningHoursParser {
} catch(NumberFormatException e){
}
}
+ public Token(TokenType tokenType, int tokenMainNumber) {
+ type = tokenType;
+ mainNumber = tokenMainNumber;
+ text = Integer.toString(mainNumber);
+ }
int mainNumber = -1;
TokenType type;
String text;
-
+ Token parent;
+
@Override
public String toString() {
- return text + " [" + type + "] ";
+ if (parent != null) {
+ return parent.text + " [" + parent.type + "] (" + text + " [" + type + "]) ";
+ } else {
+ return text + " [" + type + "] ";
+ }
}
}
@@ -1503,9 +1619,10 @@ public class OpeningHoursParser {
basic.setComment(comment);
boolean[] days = basic.getDays();
boolean[] months = basic.getMonths();
- boolean[] dayMonths = basic.getDayMonths();
+ //boolean[][] dayMonths = basic.getDayMonths();
if ("24/7".equals(localRuleString)) {
Arrays.fill(days, true);
+ basic.hasDays = true;
Arrays.fill(months, true);
basic.addTimeRange(0, 24 * 60);
rules.add(basic);
@@ -1598,10 +1715,12 @@ public class OpeningHoursParser {
private static void buildRule(BasicOpeningHourRule basic, List tokens, List rules) {
// order MONTH MONTH_DAY DAY_WEEK HOUR_MINUTE OPEN_OFF
TokenType currentParse = TokenType.TOKEN_UNKNOWN;
+ TokenType currentParseParent = TokenType.TOKEN_UNKNOWN;
List listOfPairs = new ArrayList<>();
Set presentTokens = new HashSet<>();
Token[] currentPair = new Token[2];
listOfPairs.add(currentPair);
+ Token prevToken = null;
int indexP = 0;
for(int i = 0; i <= tokens.size(); i++) {
Token t = i == tokens.size() ? null : tokens.get(i);
@@ -1614,22 +1733,48 @@ public class OpeningHoursParser {
if (currentParse == TokenType.TOKEN_MONTH || currentParse == TokenType.TOKEN_DAY_MONTH
|| currentParse == TokenType.TOKEN_DAY_WEEK || currentParse == TokenType.TOKEN_HOLIDAY) {
+ boolean tokenDayMonth = currentParse == TokenType.TOKEN_DAY_MONTH;
boolean[] array = (currentParse == TokenType.TOKEN_MONTH) ? basic.getMonths()
- : (currentParse == TokenType.TOKEN_DAY_MONTH) ? basic.getDayMonths() : basic.getDays();
+ : tokenDayMonth ? null : basic.getDays();
for (Token[] pair : listOfPairs) {
if (pair[0] != null && pair[1] != null) {
- if (pair[0].mainNumber <= pair[1].mainNumber) {
- for (int j = pair[0].mainNumber; j <= pair[1].mainNumber && j < array.length; j++) {
- array[j] = true;
- }
- } else {
- // overflow
- for (int j = pair[0].mainNumber; j < array.length; j++) {
- array[j] = true;
- }
- for (int j = 0; j <= pair[1].mainNumber; j++) {
- array[j] = true;
+ Token firstMonthToken = pair[0].parent;
+ Token lastMonthToken = pair[1].parent;
+ if (tokenDayMonth && firstMonthToken != null) {
+ if (lastMonthToken != null && lastMonthToken.mainNumber != firstMonthToken.mainNumber) {
+ Token[] p = new Token[]{firstMonthToken, lastMonthToken};
+ fillRuleArray(basic.getMonths(), p);
+
+ Token t1 = new Token(TokenType.TOKEN_DAY_MONTH, pair[0].mainNumber);
+ Token t2 = new Token(TokenType.TOKEN_DAY_MONTH, 30);
+ p = new Token[]{t1, t2};
+ array = basic.getDayMonths(firstMonthToken.mainNumber);
+ fillRuleArray(array, p);
+
+ t1 = new Token(TokenType.TOKEN_DAY_MONTH, 0);
+ t2 = new Token(TokenType.TOKEN_DAY_MONTH, pair[1].mainNumber);
+ p = new Token[]{t1, t2};
+ array = basic.getDayMonths(lastMonthToken.mainNumber);
+ fillRuleArray(array, p);
+
+ if (firstMonthToken.mainNumber <= lastMonthToken.mainNumber) {
+ for (int month = firstMonthToken.mainNumber + 1; month < lastMonthToken.mainNumber; month++) {
+ Arrays.fill(basic.getDayMonths(month), true);
+ }
+ } else {
+ for (int month = firstMonthToken.mainNumber + 1; month < 12; month++) {
+ Arrays.fill(basic.getDayMonths(month), true);
+ }
+ for (int month = 0; month < lastMonthToken.mainNumber; month++) {
+ Arrays.fill(basic.getDayMonths(month), true);
+ }
+ }
+ } else {
+ array = basic.getDayMonths(firstMonthToken.mainNumber);
+ fillRuleArray(array, pair);
}
+ } else if (array != null) {
+ fillRuleArray(array, pair);
}
} else if (pair[0] != null) {
if (pair[0].type == TokenType.TOKEN_HOLIDAY) {
@@ -1641,7 +1786,13 @@ public class OpeningHoursParser {
basic.easter = true;
}
} else if (pair[0].mainNumber >= 0) {
- array[pair[0].mainNumber] = true;
+ Token firstMonthToken = pair[0].parent;
+ if (tokenDayMonth && firstMonthToken != null) {
+ array = basic.getDayMonths(firstMonthToken.mainNumber);
+ }
+ if (array != null) {
+ array[pair[0].mainNumber] = true;
+ }
}
}
}
@@ -1664,14 +1815,19 @@ public class OpeningHoursParser {
currentPair[indexP++] = t;
if (t != null) {
currentParse = t.type;
+ currentParseParent = currentParse;
+ if (t.type == TokenType.TOKEN_DAY_MONTH && prevToken != null && prevToken.type == TokenType.TOKEN_MONTH) {
+ t.parent = prevToken;
+ currentParseParent = prevToken.type;
+ }
}
- } else if (t.type.ord() < currentParse.ord() && indexP == 0 && tokens.size() > i) {
+ } else if (t.type.ord() < currentParseParent.ord() && indexP == 0 && tokens.size() > i) {
BasicOpeningHourRule newRule = new BasicOpeningHourRule(basic.getSequenceIndex());
newRule.setComment(basic.getComment());
buildRule(newRule, tokens.subList(i, tokens.size()), rules);
tokens = tokens.subList(0, i + 1);
} else if (t.type == TokenType.TOKEN_COMMA) {
- if (tokens.size() > i + 1 && tokens.get(i + 1) != null && tokens.get(i + 1).type.ord() < currentParse.ord()) {
+ if (tokens.size() > i + 1 && tokens.get(i + 1) != null && tokens.get(i + 1).type.ord() < currentParseParent.ord()) {
indexP = 0;
} else {
currentPair = new Token[2];
@@ -1681,21 +1837,48 @@ public class OpeningHoursParser {
} else if (t.type == TokenType.TOKEN_DASH) {
} else if (t.type.ord() == currentParse.ord()) {
- if(indexP < 2) {
+ if (indexP < 2) {
currentPair[indexP++] = t;
+ if (t.type == TokenType.TOKEN_DAY_MONTH && prevToken != null && prevToken.type == TokenType.TOKEN_MONTH) {
+ t.parent = prevToken;
+ }
}
}
+ prevToken = t;
}
- if(!presentTokens.contains(TokenType.TOKEN_MONTH)) {
+ if (!presentTokens.contains(TokenType.TOKEN_MONTH)) {
Arrays.fill(basic.getMonths(), true);
+ } else {
+ if (presentTokens.contains(TokenType.TOKEN_DAY_MONTH)) {
+ basic.hasDayMonths = true;
+ }
}
- if(!presentTokens.contains(TokenType.TOKEN_DAY_WEEK) && !presentTokens.contains(TokenType.TOKEN_HOLIDAY) &&
+ if (!presentTokens.contains(TokenType.TOKEN_DAY_WEEK) && !presentTokens.contains(TokenType.TOKEN_HOLIDAY) &&
!presentTokens.contains(TokenType.TOKEN_DAY_MONTH)) {
Arrays.fill(basic.getDays(), true);
+ basic.hasDays = true;
+ } else if (presentTokens.contains(TokenType.TOKEN_DAY_WEEK)) {
+ basic.hasDays = true;
}
rules.add(0, basic);
}
+ private static void fillRuleArray(boolean[] array, Token[] pair) {
+ if (pair[0].mainNumber <= pair[1].mainNumber) {
+ for (int j = pair[0].mainNumber; j <= pair[1].mainNumber && j < array.length; j++) {
+ array[j] = true;
+ }
+ } else {
+ // overflow
+ for (int j = pair[0].mainNumber; j < array.length; j++) {
+ array[j] = true;
+ }
+ for (int j = 0; j <= pair[1].mainNumber; j++) {
+ array[j] = true;
+ }
+ }
+ }
+
private static void findInArray(Token t, String[] list, TokenType tokenType) {
for(int i = 0; i < list.length; i++) {
if(list[i].equals(t.text)) {
diff --git a/OsmAnd-java/src/test/java/net/osmand/util/OpeningHoursParserTest.java b/OsmAnd-java/src/test/java/net/osmand/util/OpeningHoursParserTest.java
index feded1d220..c59f214633 100644
--- a/OsmAnd-java/src/test/java/net/osmand/util/OpeningHoursParserTest.java
+++ b/OsmAnd-java/src/test/java/net/osmand/util/OpeningHoursParserTest.java
@@ -1,25 +1,14 @@
package net.osmand.util;
-import java.io.Serializable;
-import java.text.DateFormatSymbols;
-import java.text.MessageFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
+import net.osmand.util.OpeningHoursParser.OpeningHours;
import org.junit.Test;
-import net.osmand.util.OpeningHoursParser.OpeningHours;
-import junit.framework.Assert;
-import gnu.trove.list.array.TIntArrayList;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
/**
* Class used to parse opening hours
@@ -121,14 +110,65 @@ public class OpeningHoursParserTest {
@Test
public void testOpeningHours() throws ParseException {
- // 0. not supported MON DAY-MON DAY (only supported Feb 2-14 or Feb-Oct: 09:00-17:30)
- // parseOpenedHours("Feb 16-Oct 15: 09:00-18:30; Oct 16-Nov 15: 09:00-17:30; Nov 16-Feb 15: 09:00-16:30");
-
- // 1. not properly supported
+ // 0. not properly supported
// hours = parseOpenedHours("Mo-Su (sunrise-00:30)-(sunset+00:30)");
-
+
+ OpeningHours hours = parseOpenedHours("Apr 05-Oct 24: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("26.08.2018 15:00", hours, false);
+ testOpened("29.03.2019 15:00", hours, false);
+ testOpened("05.04.2019 11:00", hours, true);
+
+ hours = parseOpenedHours("Oct 24-Apr 05: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("26.08.2018 15:00", hours, false);
+ testOpened("29.03.2019 15:00", hours, true);
+ testOpened("26.04.2019 11:00", hours, false);
+
+ hours = parseOpenedHours("Oct 24-Apr 05, Jun 10-Jun 20, Jul 6-12: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("26.08.2018 15:00", hours, false);
+ testOpened("02.01.2019 15:00", hours, false);
+ testOpened("29.03.2019 15:00", hours, true);
+ testOpened("26.04.2019 11:00", hours, false);
+
+ hours = parseOpenedHours("Apr 05-24: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("12.10.2018 11:00", hours, false);
+ testOpened("12.04.2019 15:00", hours, true);
+ testOpened("27.04.2019 15:00", hours, false);
+
+ hours = parseOpenedHours("Apr 5: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("05.04.2019 15:00", hours, true);
+ testOpened("06.04.2019 15:00", hours, false);
+
+ hours = parseOpenedHours("Apr 24-05: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("12.10.2018 11:00", hours, false);
+ testOpened("12.04.2018 15:00", hours, false);
+
+ hours = parseOpenedHours("Apr: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("12.10.2018 11:00", hours, false);
+ testOpened("12.04.2019 15:00", hours, true);
+
+ hours = parseOpenedHours("Apr-Oct: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("09.11.2018 11:00", hours, false);
+ testOpened("12.10.2018 11:00", hours, true);
+ testOpened("24.08.2018 15:00", hours, true);
+ testOpened("09.03.2018 15:00", hours, false);
+
+ hours = parseOpenedHours("Apr, Oct: Fr 08:00-16:00");
+ System.out.println(hours);
+ testOpened("09.11.2018 11:00", hours, false);
+ testOpened("12.10.2018 11:00", hours, true);
+ testOpened("24.08.2018 15:00", hours, false);
+ testOpened("12.04.2019 15:00", hours, true);
+
// test basic case
- OpeningHours hours = parseOpenedHours("Mo-Fr 08:30-14:40"); //$NON-NLS-1$
+ hours = parseOpenedHours("Mo-Fr 08:30-14:40"); //$NON-NLS-1$
System.out.println(hours);
testOpened("09.08.2012 11:00", hours, true);
testOpened("09.08.2012 16:00", hours, false);
diff --git a/OsmAnd-telegram/res/drawable-hdpi/ic_action_location_off.png b/OsmAnd-telegram/res/drawable-hdpi/ic_action_location_off.png
new file mode 100644
index 0000000000..9462c1e31f
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-hdpi/ic_action_location_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-hdpi/ic_action_message_send_error.png b/OsmAnd-telegram/res/drawable-hdpi/ic_action_message_send_error.png
new file mode 100644
index 0000000000..a1414d274a
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-hdpi/ic_action_message_send_error.png differ
diff --git a/OsmAnd-telegram/res/drawable-hdpi/ic_action_wifi_off.png b/OsmAnd-telegram/res/drawable-hdpi/ic_action_wifi_off.png
new file mode 100644
index 0000000000..896ad28a74
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-hdpi/ic_action_wifi_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-mdpi/ic_action_location_off.png b/OsmAnd-telegram/res/drawable-mdpi/ic_action_location_off.png
new file mode 100644
index 0000000000..4dd351cafb
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-mdpi/ic_action_location_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-mdpi/ic_action_message_send_error.png b/OsmAnd-telegram/res/drawable-mdpi/ic_action_message_send_error.png
new file mode 100644
index 0000000000..34cbb70bfc
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-mdpi/ic_action_message_send_error.png differ
diff --git a/OsmAnd-telegram/res/drawable-mdpi/ic_action_wifi_off.png b/OsmAnd-telegram/res/drawable-mdpi/ic_action_wifi_off.png
new file mode 100644
index 0000000000..97a66b033c
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-mdpi/ic_action_wifi_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-xhdpi/ic_action_location_off.png b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_location_off.png
new file mode 100644
index 0000000000..dea560426a
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_location_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-xhdpi/ic_action_message_send_error.png b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_message_send_error.png
new file mode 100644
index 0000000000..3e76300bf3
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_message_send_error.png differ
diff --git a/OsmAnd-telegram/res/drawable-xhdpi/ic_action_wifi_off.png b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_wifi_off.png
new file mode 100644
index 0000000000..dd27fa07f6
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xhdpi/ic_action_wifi_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_location_off.png b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_location_off.png
new file mode 100644
index 0000000000..cde23c970f
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_location_off.png differ
diff --git a/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_message_send_error.png b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_message_send_error.png
new file mode 100644
index 0000000000..4580276de8
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_message_send_error.png differ
diff --git a/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_wifi_off.png b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_wifi_off.png
new file mode 100644
index 0000000000..8d35b7a315
Binary files /dev/null and b/OsmAnd-telegram/res/drawable-xxhdpi/ic_action_wifi_off.png differ
diff --git a/OsmAnd/res/values-da/phrases.xml b/OsmAnd/res/values-da/phrases.xml
index 374d2fff90..693801b9a7 100644
--- a/OsmAnd/res/values-da/phrases.xml
+++ b/OsmAnd/res/values-da/phrases.xml
@@ -3962,4 +3962,6 @@
Licensklasser
+Bakke
+
diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml
index 08ccacebfd..e803e2e9c4 100644
--- a/OsmAnd/res/values-da/strings.xml
+++ b/OsmAnd/res/values-da/strings.xml
@@ -2536,7 +2536,7 @@ Repræsenterer område: %1$s x %2$sKortunderlejring ændret til \"%s\".Tryk på genvejsknappen gennemløber nedenstående liste.Opdel automatisk optagelser efter et ophold
- Start et nyt segment efter ophold på 6 min., et nyt spor efter 2 t eller en ny fil efter let ængere ophold, hvis datoen er ændret.
+ Start et nyt segment efter ophold på 6 min., et nyt spor efter 2 timer eller en ny fil efter et længere ophold, hvis datoen er ændret.Vis dybdekonturer og -punkter.Havdybdekonturer
@@ -3206,4 +3206,12 @@ Repræsenterer område: %1$s x %2$sGiv OsmAnd tilladelse til placering for at fortsætte.SortDer er andre transportmidler ved dette stop.
+ Slet kortmarkør \'%s\'\?
+ Rediger kortmarkør
+ Tredjepartsprogram
+ Søg efter gade
+ Start søgning fra byen
+ Gendan
+ Markører tilføjet som en gruppe af favoritter eller GPX rutepunkter markeret passeret vil forblive på kortet. Hvis gruppen ikke er aktiv, vil mærkerne forsvinde fra kortet.
+ Behold passerede markører på kortet
diff --git a/OsmAnd/res/values-eo/phrases.xml b/OsmAnd/res/values-eo/phrases.xml
index e422338004..31804463f9 100644
--- a/OsmAnd/res/values-eo/phrases.xml
+++ b/OsmAnd/res/values-eo/phrases.xml
@@ -840,9 +840,9 @@
Skivojo alpa (malsuprenira)Skivojo nordia (skikurada)Skivojo ski-ekskursuma
- Skivojo skikurada
- Skivojo glitveturila
- Skivojo glitveturila (tirata de hundoj)
+ Skivojo marŝada
+ Skivojo glitveturila (tirata de hundoj)
+ Skivojo glitveturilaSkivojo neĝ-parkaSkivojo infanludejaSkivojo glitkurada
diff --git a/OsmAnd/res/values-eu/phrases.xml b/OsmAnd/res/values-eu/phrases.xml
index cd47c8333f..b1ebee835f 100644
--- a/OsmAnd/res/values-eu/phrases.xml
+++ b/OsmAnd/res/values-eu/phrases.xml
@@ -3870,4 +3870,6 @@
Lizentzia klaseak
+Muinoa
+
diff --git a/OsmAnd/res/values-eu/strings.xml b/OsmAnd/res/values-eu/strings.xml
index 10e3644b81..e3d96e90d1 100644
--- a/OsmAnd/res/values-eu/strings.xml
+++ b/OsmAnd/res/values-eu/strings.xml
@@ -3144,13 +3144,19 @@ Area honi dagokio: %1$s x %2$s
\nBidea betetzen…Sakatu botoi bat eta entzun dagokion ahots-deskripzioa falta diren edo gaizki dauden deskripzioan antzemateko.
-• Karaktere mapa ez latinoetan gertatzen zen kraskatzea konponduta
+• Gailu batzuetan gertatzen zen kaskatzea konponduta
+\n
+\n• Markatzaileen ezaugarri berria: Bistaratu iragandako markatzaileak
+\n
+\n• Bilaketa historiak aurretik bilatutako kategoriak bistaratzen ditu
+\n
+\n• Karaktere mapa ez latinoetan gertatzen zen kraskatzea konponduta
\n
\n • Android 8.0 gailuetan gertatzen ziren errendatze abiadura arazoak konponduta
\n
\n • Poligono objektuak editatzeko euskarria (Ez-zerbitzua)
-\n
-\n• Distantziaren neurketa: Neurketa botoia gehitu da laster-menuko ekintzetara
+\n
+\n• Distantziaren neurketa: Neurketa botoia gehitu da laster-menuko ekintzetara
\nEman OsmAnd-i kokalekua eskuratzeko baimena jarraitzeko.Beltza
@@ -3160,4 +3166,7 @@ Area honi dagokio: %1$s x %2$sGogokoen talde gisa gehitutako markatzaileak edo pasatutako gisa markatutako GPX bide-puntuak mapan mantenduko dira. Taldea aktibo ez badago, markatzaileak mapatik desagertuko dira.Mantendu pasatutako markatzaileak mapanGarraio gehiago daude geldiune honetan.
+ Ezabatu \'%s\' mapa-markatzailea\?
+ Editatu mapa-markatzailea
+ Hirugarrengoen aplikazioa
diff --git a/OsmAnd/res/values-he/phrases.xml b/OsmAnd/res/values-he/phrases.xml
index ce2971ef97..4231ceafad 100644
--- a/OsmAnd/res/values-he/phrases.xml
+++ b/OsmAnd/res/values-he/phrases.xml
@@ -2202,4 +2202,65 @@
אספקה חקלאיתציוד ריצוף
-
+ בחדר נפרד
+ בחדר מבודד
+ מוקדש למעשנים
+
+ אגרה
+ ללא אגרה
+ אגרה למשאיות
+ כן
+ כן
+ לא
+ רק כאשר מותר לחצות
+
+ תחנת הצלה
+
+ אזור שירות
+ כיכר מזערית
+ רשת אלחוטית
+ מסוף
+ חיבור קווי
+ סוג הגישה לאינטרנט: ציבורית
+ סוג הגישה לאינטרנט: שירות
+ אין גישה לאינטרנט
+ יש גישה לאינטרנט
+
+ רוחב מרבי
+ קוד IATA
+ קוד ICAO
+ קוד FAA
+
+ סוג יצירת האומנות: מוצג תלת ממדי
+ סוג יצירת האומנות: פיסול
+ סוג יצירת האומנות: ציור קיר
+ סוג יצירת האומנות: אדריכלות
+ סוג יצירת האומנות: ציור
+ סוג יצירת האומנות: אבן
+ סוג יצירת האומנות: פסל ראש וכתפיים (פרוטומה/בוסטה)
+ סוג יצירת האומנות: מיצב
+ סוג יצירת האומנות: פסיפס
+ סוג יצירת האומנות: תבליט
+ סוג יצירת האומנות: גרפיטי
+ סוג יצירת האומנות: מזרקה
+
+ רוחב
+
+ אדריכל/ית
+
+ אדריכלות: מודרנית
+ אדריכלות: נאוקלסיציזם סטליניסטי
+ בינלאומי
+ אזורי
+ ציבורי
+ צבאי
+ צבאי/ציבורי
+ פרטי
+
+ פיר אוורור
+
+ סוגי רישיונות נהיגה
+
+ גבעה
+
+
diff --git a/OsmAnd/res/values-it/phrases.xml b/OsmAnd/res/values-it/phrases.xml
index 3153d7881b..cf19f94d35 100644
--- a/OsmAnd/res/values-it/phrases.xml
+++ b/OsmAnd/res/values-it/phrases.xml
@@ -741,8 +741,8 @@
Tipo di pagamentoCarte carburanteUlteriori
- Tipo di accesso Internet
- Servizio biciclette
+ Tipo di accesso a internet
+ Servizio per bicicletteTipoTipoTipo
@@ -1277,7 +1277,7 @@
Tiro con l\'arcoClub etnicoFrangiflutti
- Tipo vendita
+ Tipo di venditaCampo scoutGuidare attraversoNegozio di beneficenza
diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml
index 56b00a8f12..39437a1b74 100644
--- a/OsmAnd/res/values-it/strings.xml
+++ b/OsmAnd/res/values-it/strings.xml
@@ -2390,7 +2390,7 @@ Se ami OsmAnd e OSM e vuoi sostenerli, questo è un modo perfetto per farlo.Calcolo del percorsoNon hai ancora nessun file GPXÈ inoltre possibile aggiungere file GPX alla cartella
- Aggiungi traccia
+ Aggiungi altri…Aspetto
@@ -3079,12 +3079,12 @@ Rappresenta l\'area: %1$s x %2$s
\n"Modifica le azioniPer favore invia una schermata di questa notifica a support@osmand.net
- Il nodo o il percorso non è stato trovato.
- Nessun risultato di ricerca?
-\nDacci un ritorno
+ Non è possibile trovare il nodo o il percorso.
+ Nessun risultato\?
+\nDacci un feedback• Navigazione: corretta la barra di avanzamento, veloce inversione dei punti d\'inizio e fine percorso
\n
-\n • Marcatori mappa: corretto la visualizzazione o meno dei gruppi, la possibilità di non visualizzare i marcatori dalla mappa
+\n • Marcatori mappa: corretto la visualizzazione o meno dei gruppi, aggiunta la possibilità di non visualizzare i marcatori dalla mappa
\n
\n • Modifiche OSM: possibilità di modificare elementi non puntuali e segmenti, correzione di commenti mancanti nelle note, backup delle modifiche
\n
@@ -3098,8 +3098,8 @@ Rappresenta l\'area: %1$s x %2$s
\n
\n
Sottoponi la via…
- Incrementa il raggio di ricerca a %1$s
- Invieremo le tue ricerche: \"%1$s\", e la tua localizzazione.
Non raccogliamo informazioni personali, abbiamo solo bisogno dei dati delle ricerche per migliorare l\'algoritmo di ricerca.
+ Aumenta il raggio di ricerca a %1$s
+ Invieremo la tua ricerca \"%1$s\" oltre alla tua localizzazione.
Non raccogliamo informazioni personali, abbiamo solo bisogno dei dati delle ricerche per migliorare l\'algoritmo di ricerca. Inviare i dati delle ricerche?MondoPunto %1$s eliminato
@@ -3108,21 +3108,30 @@ Rappresenta l\'area: %1$s x %2$s
Salva come tracciaHai aggiunto %1$s punti. Digita il nome del file e tappa su \"Salva\".Tap sul pulsante e ascolta l\'avviso vocale corrispondente per identificare gli avvisi errati o mancanti
-• Corretto l\'arresto in avvio con le mappe non latine
-\n
-\n• Migliorati i problemi di velocità di disegno nei dispositivi Android 8.0
-\n
-\n• Supporto alla modifica degli oggetti poligonali (non amenità)
-\n
+• Sistemato il crash all\'avvio che avveniva con alcuni dispositivi
\n
+\n • Nuova funzione Marcatori: mostra i marcatori che sono stati già superati
+\n
+\n • Cerca per cronologia ora mostra le categorie che si sono cercate precedentemente
+\n
+\n • Corretto l\'arresto in avvio con le mappe non latine
+\n
+\n • Migliorati i problemi di velocità di disegno nei dispositivi Android 8.0
+\n
+\n • Supporto alla modifica degli oggetti poligonali (non amenità)
+\n
+\n • Misuratore di distanze: aggiunto il bottone Misura la distanza alle azioni nel menù laterale
\n
- Per favore dai OsmAnd il permesso alla localizzazione per continuare.
+ Per favore concedi il permesso a OsmAnd di accedere alla geolocalizzazione per continuare.Grazie per il feedback
- Ricerca per strada
+ Ricerca stradaInizia la ricerca dalla cittàRipristina
- Tenere passati marcatori sulla mappa
+ Tenere i marcatori superati sulla mappaC\'è più trasporto su questa fermata.
- Marcatori aggiunti come gruppo di Preferiti o come punti GPX marcati come Superati rimarranno sulla mappa. Se il gruppo non è attivo i marcatori spariranno dalla mappa.
+ I marcatori aggiunti come gruppo di Preferiti o come punti GPX marcati come Superati rimarranno sulla mappa. Se il gruppo non è attivo i marcatori spariranno dalla mappa.Nero
+ Eliminare il marcatore \'%s\'\?
+ Modifica marcatore
+ Applicazione di terze parti
diff --git a/OsmAnd/res/values-pl/phrases.xml b/OsmAnd/res/values-pl/phrases.xml
index b7a2aad0d0..707fce8a89 100644
--- a/OsmAnd/res/values-pl/phrases.xml
+++ b/OsmAnd/res/values-pl/phrases.xml
@@ -644,8 +644,8 @@
Domek letniskowyApartamentTrasa piesza
- Trasa saneczkarska
- Trasa saneczkarska (zaprzęgi)
+ Trasa saneczkarska (zaprzęgi)
+ Trasa saneczkarskaTrasa dla dzieciKlub ze striptizemOśrodek nadmorski
diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml
index 85e4a85aa8..288ef33aa1 100644
--- a/OsmAnd/res/values-pt-rBR/strings.xml
+++ b/OsmAnd/res/values-pt-rBR/strings.xml
@@ -2235,7 +2235,7 @@ Pôr do Sol: %2$sEvitar estradas de gelo, vausEvitar estradas de gelo e vaus.Limite para orientação do mapa
- Mostrar diálogo \'Navegação finalizada\'
+ Mostrar \'Navegação finalizada\'Cache de quadrículaRégua de raioExibir a partir do nível de zoom
diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml
index 8f7437fc79..83040fa499 100644
--- a/OsmAnd/res/values-ru/strings.xml
+++ b/OsmAnd/res/values-ru/strings.xml
@@ -100,7 +100,7 @@
ОтправлениеПрибытиеЦвет
- Выберите папку для GPX файла
+ Выберите папку для файла GPXПереместитьТрекиСпуск
@@ -168,8 +168,8 @@
Выгрузить POIПостроение маршрута
- У вас пока нет треков
- Вы также можете добавить треки в папку
+ У вас пока нет файлов GPX
+ Вы также можете добавить файлы GPX в папкуДобавитьВид
@@ -215,7 +215,7 @@
Сохранить фильтрУдалить фильтрНовый фильтр
- %s GPX трека(ов) выбрано
+ %s файла(ов) GPX выбраноИзменить положение маркераТекущий путьНавигация OsmAnd Live
@@ -365,7 +365,7 @@
ПлагиныПлагины активируют дополнительные возможности приложения.Плагины
- С помощью этого плагина OsmAnd может быть использован для улучшения OSM через создание или изменение объектов OSM POI, открытие или комментирование OSM заметок, а также отправку записанные GPX файлов. OSM развивается обществом, глобальный проект создания карты общей собственности. Для получения дополнительной информации, пожалуйста, обращайтесь на https://openstreetmap.org. Активное участие ценится, и взносы могут быть сделаны непосредственно через OsmAnd, если вы укажете свои учетные данные OSM в настройках.
+ С помощью этого плагина OsmAnd может быть использован для улучшения OSM через создание или изменение объектов OSM POI, открытие или комментирование OSM заметок, а также отправку записанных файлов GPX. OSM развивается обществом, глобальный проект создания карты общей собственности. Для получения дополнительной информации, пожалуйста, обращайтесь на https://openstreetmap.org. Активное участие ценится, и взносы могут быть сделаны непосредственно через OsmAnd, если вы укажете свои учетные данные OSM в настройках.Векторные карты могут отображаться быстрее. Поддерживается не всеми устройствами.Воспроизвести команды выбранным голосомОтладка и разработка
@@ -837,8 +837,8 @@
Автоматически изменять масштаб карты при изменении скорости (пока карта синхронизирована с текущим положением).АвтомасштабДополнительные настройки
- Сохранить текущий трек на SD-карту сейчас.
- Сохранить текущий трек GPX
+ Сохранить текущий трек как файл GPX.
+ Сохранить текущий трекВыберите интервал для записи трека во время навигации.Интервал записи во время навигацииВо время навигации треки GPX будут автоматически сохранены в папку с треками.
@@ -1679,7 +1679,7 @@
ПродолжительностьЗапись трека в файл GPXИнтервал записи
- Общая запись местоположения в файл GPX может быть включена или выключена с помощью виджета записи GPX на экране карты.
+ Ведение записи местоположения в файл GPX можно включить или выключить с помощью виджета записи GPX на экране карты."Плагин активирует функции для записи и сохранения ваших треков вручную нажатием на виджет записи GPX на экране карты, или также автоматически записывает все ваши маршруты навигации в файл GPX.
\n
\nЗаписанными треками можно поделиться с вашими друзьями или использовать их для вклада в OSM. Спортсмены могут использовать записанные треки для контроля за тренировками. Некоторый базовый анализ треков может быть выполнен непосредственно в OsmAnd, например, время прохождения круга, средняя скорость и т.д., треки, конечно, позднее также могут быть проанализированы в специальных инструментах анализа сторонних производителей."
@@ -1814,7 +1814,7 @@
Выбрать всеОчиститьСохранить
- Сохранить как новый GPX трек
+ Сохранить как новый файл GPXПереименоватьУдалитьУдалить все
@@ -2056,7 +2056,7 @@
Показывать при запускеВы уверены?Все несохраненные изменения будут потеряны. Продолжить?
- Моделировать ваше местоположение, используя рассчитанный маршрут или записанный GPX.
+ Моделировать ваше местоположение, используя рассчитанный маршрут или записанный трек GPX.Остановить моделирование своего местоположения.Добавить новуюВыберите категорию
@@ -2150,8 +2150,8 @@
Время:Кнопка меню открывает панель управления, а не менюДоступ с карты
- Удалить точку GPX?
- Редактировать точку GPX
+ Удалить путевую точку GPX\?
+ Редактировать путевую точку GPXИзбегать лестницИзбегать лестницИзбегать пересечения границы
@@ -2346,7 +2346,7 @@
Прокладывайте маршруты и открывайте новые для себя места без подключения к ИнтернетуРазрешить доступ к местоположениюДать разрешение
- OsmAnd будет хранить данные (карты, маршруты и пр.) в %1$s.
+ Хранилище данных OsmAnd (для карт, файлов GPX и пр.): %1$s.Свободное местоОпределение местоположения…Требуется загрузить карты
@@ -2464,7 +2464,7 @@
Откорректированное расстояниеУстановите Mapillary, чтобы добавить одну или несколько фотографий к этому месту на карте.Высота маршрута
- Имя GPX файла:
+ Имя файла GPX:Показать на карте после сохраненияПросмотрите карту и добавьте точкиИзмерить расстояние
@@ -2502,7 +2502,7 @@
В этом годуПлан маршрутаВвод координат
- Сохранить как GPX файл
+ Сохранить как файл GPXПереместить в историюГруппа будет выключена при следующем запуске приложения.Показывать стрелки на карте
@@ -2517,7 +2517,7 @@
Мое местоположениеФинишСортировать
- Экспорт маркеров в следующий GPX файл:
+ Экспорт маркеров в следующий файл GPX:МаркерыИзменить заметкуИзменить заметку OSM
@@ -2531,8 +2531,8 @@
Смена ориентации картыВыберите ниже скорость, при которой переключается ориентация карты с \"По направлению движения\" на \"По направлению компаса\".Все маркеры перемещены в историю
- Маркер карты перемещен в историю
- Маркер карты перемещен в действующие
+ Маркер перемещен в историю
+ Маркер перемещен в действующиеУказатель расстояния
@@ -2590,7 +2590,7 @@
Выберите категорию избранных для добавления к маркерам.Категория избранныхДобавить группу
- Импортировать группу из избранных или GPX путевых точек.
+ Импортировать группу из избранных или путевых точек GPX.Создайте маркеры карт!Длинное или короткое нажатие на нужное место, а затем на флажок маркера.Импорт групп
@@ -2618,7 +2618,7 @@
Показать цифровую панельНажатие на карте переключает кнопки управления и виджеты.
- могут быть импортированы как избранные точки или как GPX файл.
+ могут быть импортированы как избранные точки или как файл GPX.БольшеИмпортировать как файл GPXИмпортировать как избранные
@@ -2813,7 +2813,7 @@
Показать/скрыть заметки OSM на карте.GPX - подходит для экспорта в JOSM и другие OSM редакторы.OSC - подходит для экспорта в OpenStreetMap.
- GPX файл
+ Файл GPXOSC файлВыберите тип файлаВыберите тип экспорта: заметки OSM, POI или оба.
@@ -2993,7 +2993,10 @@
Поиск улицыНачать поиск с городаВосстановить
- Маркеры, добавленные как группа избранных или GPX путевых точек и отмеченные как пройденные, останутся на карте. Если группа не активна, маркеры исчезнут с карты.
+ Маркеры, добавленные как группа избранных или путевых точек GPX и отмеченные как пройденные, останутся на карте. Если группа не активна, маркеры исчезнут с карты.Оставить пройденные маркеры на картеНа этой остановке есть другие транспортные средства.
+ Удалить маркер \'%s\'\?
+ Редактировать маркер
+ Стороннее приложение
diff --git a/OsmAnd/res/values-sl/strings.xml b/OsmAnd/res/values-sl/strings.xml
index 1f9ed61ecd..9c0fc1c3d3 100644
--- a/OsmAnd/res/values-sl/strings.xml
+++ b/OsmAnd/res/values-sl/strings.xml
@@ -1,4 +1,5 @@
-
+
+PoiščiIskanje podatkov
@@ -364,7 +365,7 @@ Sorazmerna velikost pomnilnika je %4$s MB (omejitev na androidu je %5$s MB, na d
Odpeljite vozilo s parkiriščaObvestilo, da odpeljite vozilo s parkirišča, je bilo dodano v koledar. Ostalo bo zapisano, dokler ga ne izbrišete ročno.Nastavi časovno omejitev parkiranja
- Ali želite izbrisati označbo mesta, kjer je vozilo parkirano?
+ Ali želite izbrisati označbo mesta parkiranja\?Izbriši označbo mesta parkiranjaIzbor vrste parkiranjaČasovno omejeno
@@ -2129,7 +2130,7 @@ Omogoča tudi dodajanje opomb v koledar za prikaz opomnikov ob daljših časih p
Omogoči možnosti označb zemljevida.Ali želite odstraniti vse dejavne označbe?
- Ali res želite počistiti zgodovino označbe?
+ Ali želite počistiti zgodovino označb\?Dejavne označbeOznačbe zemljevidaOznačba zemljevida
@@ -2440,7 +2441,7 @@ Koda predstavlja območje: %1$s x %2$s
Samodejno razdeli beleženje po vmesnih točkahZačne z novim odsekom po 6-minutnem premoru, novo sled po 2-urnem premoru oziroma s povsem novo datoteko beleženja, če je zamik čez datumsko mejo.
- S pritiskom na gumb dejanja bo dodana označba na zemljevid na trenutno sredinsko točko na zaslonu.
+ S pritiskom na gumb dejanja bo dodana označba na trenutno sredinsko točko.S pritiskom na gumb dejanja bo dodana vmesna točka GPX na trenutno sredinsko točko na zaslonu.S pritiskom na gumb dejanja bo dodano zvočno sporočilo na trenutno sredinsko točko na zaslonu.S pritiskom na gumb dejanja bo dodano video sporočilo na trenutno sredinsko točko na zaslonu.
@@ -2987,4 +2988,12 @@ Koda predstavlja območje: %1$s x %2$s
Iskanje pripadajočega prispevka na WikipedijiPrispevka ni mogoče najtiKako odpreti prispevek na Wikipediji?
-
\ No newline at end of file
+Ali res želite izbrisati označbo »%s«\'\?
+ Uredi označbo zemljevida
+ Programi tretjih oseb
+ Iskanje ulice
+ Začni z iskanjem mesta
+ Obnovi
+ Zahvaljujemo se vam za vaš odziv
+ Svet
+
diff --git a/OsmAnd/res/values-uk/phrases.xml b/OsmAnd/res/values-uk/phrases.xml
index 0a5192996b..23b43b00ec 100644
--- a/OsmAnd/res/values-uk/phrases.xml
+++ b/OsmAnd/res/values-uk/phrases.xml
@@ -157,8 +157,8 @@
Благодійний магазинМедичне постачанняФотомагазин
- Лежачий поліцейський
- Штучне підвищення
+ Штучна дорожня нерівність
+ \"Лежачий поліцейський\"ШиканаМагазин шкіри, галантареяМузичний магазин
@@ -173,9 +173,9 @@
ПіротехнікаМагазин зброї
- Декілька лежачих поліцейських
+ \"Берлінська подушка\"Шумові полоси
- Довгий лежачий поліцейський
+ Підвищений пішохідний перехідЗвуження дорогиСвітлофор
@@ -264,7 +264,7 @@
Зона відпочинкуКриниця
- Напірна труба
+ Водорозбірна колонкаПішохідний перехідЕнергетичний магазин
@@ -1269,7 +1269,7 @@
Електронна поштаФаксФейсбук
- Твіттер
+ TwitterСкайпЮтюбІнстаграм
@@ -1761,7 +1761,7 @@
Хрест на вершині: єТрадиційна монгольська
- Монети по 0,5$
+ Монети по $0,5Колишній тюремний табірТрадиційна тибетськаМонети по 50c, 1€ й 2€
@@ -1878,7 +1878,7 @@
Картки UTA не приймаютьсяЗагальна хірургіяСтавок
- Efectivo
+ ГотівкаРадіологіяПожежний кран
@@ -2150,7 +2150,7 @@
Бар\'єр на переїзді: половиннийAvantCardАрхітектурний стиль: конструктивізм
- Цивілізація: нурагічна (18 ст. до н.е. - 2 ст. н.е.)
+ Цивілізація: нурагічна (18 ст. до н.е. – 2 ст. н.е.)Бар\'єр на переїзді: подвійний половиннийАрхітектурний стиль: umgebindeЦивілізація: етруски (XII - VI ст. до н.е.)
@@ -3191,7 +3191,7 @@
Ремонт мотоциклівРтутьТролейбус
- Вирощується культура: кормова рослина
+ Вирощується культура: свійська птицяГлибинна психологіяМета вибуху: промислове застосування, сейсмічне зондуванняОбслуговування в стаціонарі: ні
@@ -3861,7 +3861,11 @@
Мінне поле
-Місце об\'єднання автомобілів
+Точка кар-шерінгуРуїни
-
+ Ліцензійні класи
+
+ Пагорб
+
+
diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml
index ee998b672c..aaa095fef9 100644
--- a/OsmAnd/res/values-uk/strings.xml
+++ b/OsmAnd/res/values-uk/strings.xml
@@ -2,7 +2,7 @@
Швидко
- Круговий рух : Візьміть %1$d з’їзд та продовжуйте рух
+ Круговий рух : Прямуйте до %1$d з’їзду та продовжуйте рухТримайтесь ліворучТримайтесь праворучВідображати тільки контури, без заливки.
@@ -1824,7 +1824,7 @@
У багатьох країнах (Німеччина, Франція, Італія та інші) використання детекторів камер контролю швидкості не дозволено законом. OsmAnd не несе ніякої відповідальності, якщо Ви порушите закон. Будь ласка, натисніть кнопку „Так“, тільки якщо ви маєте право використовувати цю функцію.Звантаження мапЩоб правильно показувати дорожні знаки та правила дорожнього руху, будь ласка, виберіть ваш регіон:
- OsmAnd забезпечує повністю автономний (оффлайн) перегляд мап і навігацію!
+ OsmAnd забезпечує перегляд глобальної автономної (офлайн-) мапи і автономну навігацію.Ласкаво просимоПоточний маршрутЗміни OSM додані до локального набору змін
@@ -2221,7 +2221,7 @@
Недостатньо пам\'яті!
Необхідно {3} МБ тимчасової та {1} МБ постійної пам\'яті.
На разі доступно лише {2} МБ.
- Звантажити {0} файл(їв)? Використовується {3} МБ тимчасової та {1} МБ постійної пам’яті (наразі вільно лише {2} МБ).
+ Звантажити {0} файл(ів)\? Використовується {3} Мб тимчасової та {1} Мб постійної пам’яті (наразі вільно лише {2} Мб)ПожертвуванняПідписатисяНе показувати моє ім\'я у звітах
@@ -2518,7 +2518,7 @@
Виявлено дублікат іменіНатискання на цю кнопку показує або приховує POI на мапі.Виберіть категорію (опціонально).
- Натискання на цю кнопку циклічно перемикає елементи списку нижче.
+ Натискання на цю кнопку циклічно гортає елементи списку нижче.Змінити мапу покриттяМапи покриттяДодати мапу покриття
@@ -3180,14 +3180,19 @@
\nНадішліть нам відгук
Створюється шлях…Натисніть кнопку та прослуховуйте відповідну голосову підказку, щоб визначити відсутні або хибні підказки.
-• Виправлено аварійне завершення програми при запуску з нелатинськими мапами
+• Виправлено аварійне завершення програми при запуску, що траплялося на деяких пристроях
+\n
+\n• Нова можливість Позначок: відображати пройдені позначки
+\n
+\n• Історія пошуку тепер показує категорії, які ви раніше шукали
+\n
+\n• Виправлено аварійне завершення програми при запуску з нелатинськими мапами
\n
\n• Підвищено швидкість промальовки на пристроях з Android 8.0
\n
\n• Підтримка редагування полігональних (не-amenity) об\'єктів
\n
\n• Вимірювання відстані: додано кнопку «Виміряти» до Дій у контекстному меню
-\n
\nБудь ласка, надайте OsmAnd дозвіл визначати місцезнаходження для того, щоб продовжити.Чорний
@@ -3197,4 +3202,7 @@
Позначки, додані як група Закладок або маршрутних точок GPX і позначені пройденими, залишаться на мапі. Якщо група неактивна, позначки зникнуть з мапи.Залишити пройдені позначки на мапіНа цій зупинці є інші транспортні засоби.
+ Видалити позначку мапи \'%s\'\?
+ Редагувати позначку мапи
+ Стороння програма
diff --git a/OsmAnd/res/values-zh-rTW/phrases.xml b/OsmAnd/res/values-zh-rTW/phrases.xml
index c46abaa967..2a053495e7 100644
--- a/OsmAnd/res/values-zh-rTW/phrases.xml
+++ b/OsmAnd/res/values-zh-rTW/phrases.xml
@@ -1041,7 +1041,7 @@
有監管沒有監管磨房水塘
- Twitter
+ 推特SkypeYoutubeInstagram
diff --git a/OsmAnd/res/values/phrases.xml b/OsmAnd/res/values/phrases.xml
index dd13429e5c..b0b78249dc 100644
--- a/OsmAnd/res/values/phrases.xml
+++ b/OsmAnd/res/values/phrases.xml
@@ -1024,6 +1024,7 @@
BankATM
+ ATMPayment terminalMoney lenderPawnbroker
diff --git a/OsmAnd/src/net/osmand/plus/ApplicationMode.java b/OsmAnd/src/net/osmand/plus/ApplicationMode.java
index 0ca973cdbc..fc608c9340 100644
--- a/OsmAnd/src/net/osmand/plus/ApplicationMode.java
+++ b/OsmAnd/src/net/osmand/plus/ApplicationMode.java
@@ -27,10 +27,10 @@ public class ApplicationMode {
public static final ApplicationMode CAR = create(R.string.app_mode_car, "car").speed(15.3f, 35).carLocation().
icon(R.drawable.map_action_car_dark, R.drawable.ic_action_car_dark).reg();
- public static final ApplicationMode BICYCLE = create(R.string.app_mode_bicycle, "bicycle").speed(5.5f, 15).arrivalDistance(60).bicycleLocation().
+ public static final ApplicationMode BICYCLE = create(R.string.app_mode_bicycle, "bicycle").speed(5.5f, 15).arrivalDistance(60).offRouteDistance(50).bicycleLocation().
icon(R.drawable.map_action_bicycle_dark, R.drawable.ic_action_bicycle_dark).reg();
- public static final ApplicationMode PEDESTRIAN = create(R.string.app_mode_pedestrian, "pedestrian").speed(1.5f, 5).arrivalDistance(45).
+ public static final ApplicationMode PEDESTRIAN = create(R.string.app_mode_pedestrian, "pedestrian").speed(1.5f, 5).arrivalDistance(45).offRouteDistance(20).
icon(R.drawable.map_action_pedestrian_dark, R.drawable.ic_action_pedestrian_dark).reg();
public static final ApplicationMode AIRCRAFT = create(R.string.app_mode_aircraft, "aircraft").speed(40f, 100).carLocation().
@@ -169,6 +169,11 @@ public class ApplicationMode {
applicationMode.arrivalDistance = arrivalDistance;
return this;
}
+
+ public ApplicationModeBuilder offRouteDistance(int offRouteDistance) {
+ applicationMode.offRouteDistance = offRouteDistance;
+ return this;
+ }
}
private static ApplicationModeBuilder create(int key, String stringKey) {
@@ -361,6 +366,10 @@ public class ApplicationMode {
return arrivalDistance;
}
+ public int getOffRouteDistance() {
+ return offRouteDistance;
+ }
+
public boolean isDerivedRoutingFrom(ApplicationMode mode) {
return this == mode || getParent() == mode;
}
@@ -374,6 +383,7 @@ public class ApplicationMode {
private float defaultSpeed = 10f;
private int minDistanceForTurn = 50;
private int arrivalDistance = 90;
+ private int offRouteDistance = 350;
private int bearingIconDay = R.drawable.map_pedestrian_bearing;
private int bearingIconNight = R.drawable.map_pedestrian_bearing_night;
private int headingIconDay = R.drawable.map_pedestrian_location_view_angle;
diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
index 2f1c9ec662..3963e86501 100644
--- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java
+++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java
@@ -723,7 +723,7 @@ public class OsmandSettings {
public final CommonPreference WIKI_ARTICLE_SHOW_IMAGES = new EnumIntPreference<>("wikivoyage_show_imgs", WikiArticleShowImages.OFF, WikiArticleShowImages.values()).makeGlobal();
public final CommonPreference SELECT_MARKER_ON_SINGLE_TAP = new BooleanPreference("select_marker_on_single_tap", false).makeProfile();
- public final CommonPreference KEEP_PASSED_MARKERS_ON_MAP = new BooleanPreference("keep_passed_markers_on_map", true).makeProfile();
+ public final CommonPreference KEEP_PASSED_MARKERS_ON_MAP = new BooleanPreference("keep_passed_markers_on_map", false).makeProfile();
public final CommonPreference COORDS_INPUT_USE_RIGHT_SIDE = new BooleanPreference("coords_input_use_right_side", true).makeGlobal();
public final OsmandPreference COORDS_INPUT_FORMAT = new EnumIntPreference<>("coords_input_format", Format.DD_MM_MMM, Format.values()).makeGlobal();
diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
index 930c181388..ee9ccb467f 100644
--- a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
+++ b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java
@@ -246,6 +246,21 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable
return amenityList;
}
+ public double getSearchRadius(int radius) {
+ if (radius < 0) {
+ distanceInd = 0;
+ } else if (radius < distanceToSearchValues.length) {
+ distanceInd = radius;
+ } else {
+ distanceInd = distanceToSearchValues.length - 1;
+ }
+ return distanceToSearchValues[distanceInd] * 1000;
+ }
+
+ public int getMaxSearchRadiusIndex() {
+ return distanceToSearchValues.length - 1;
+ }
+
public boolean isAutomaticallyIncreaseSearch() {
return true;
}
diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java
index 645a8c17eb..07beecfc44 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java
@@ -404,7 +404,7 @@ public class RouteCalculationResult {
}
- if(delta > 45 && delta < 315){
+ if(delta > 30 && delta < 330){
if(delta < 60){
type = TurnType.valueOf(TurnType.TSLL, leftSide);
diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
index 12f95f64e9..df11e56b6e 100644
--- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
+++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java
@@ -363,7 +363,7 @@ public class RoutingHelper {
voiceRouter.interruptRouteCommands();
voiceRouterStopped = true; // Prevents excessive execution of stop() code
}
- if (distOrth > 350) {
+ if (distOrth > mode.getOffRouteDistance()) {
voiceRouter.announceOffRoute(distOrth);
}
}
diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java
index b32c0c0751..d3d70a0e8d 100644
--- a/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java
+++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchHelper.java
@@ -324,6 +324,7 @@ public class QuickSearchHelper implements ResourceListener {
}
public static class SearchOnlineApi extends SearchBaseAPI {
+ private static final int SEARCH_RADIUS_INCREMENT = 3;
private OsmandApplication app;
private NominatimPoiFilter filter;
@@ -338,7 +339,7 @@ public class QuickSearchHelper implements ResourceListener {
public boolean search(SearchPhrase phrase, SearchResultMatcher matcher) throws IOException {
double lat = phrase.getSettings().getOriginalLocation().getLatitude();
double lon = phrase.getSettings().getOriginalLocation().getLongitude();
- String text = phrase.getUnknownSearchPhrase();
+ String text = phrase.getRawUnknownSearchPhrase();
filter.setFilterByName(text);
publishAmenities(phrase, matcher, filter.initializeNewSearch(lat, lon,
-1, null, phrase.getRadiusLevel() + 3));
@@ -379,6 +380,21 @@ public class QuickSearchHelper implements ResourceListener {
sr.preferredZoom = 17;
return sr;
}
+
+ @Override
+ public int getMinimalSearchRadius(SearchPhrase phrase) {
+ return (int)filter.getSearchRadius(phrase.getRadiusLevel() + SEARCH_RADIUS_INCREMENT);
+ }
+
+ @Override
+ public int getNextSearchRadius(SearchPhrase phrase) {
+ return (int)filter.getSearchRadius(phrase.getRadiusLevel() + SEARCH_RADIUS_INCREMENT + 1);
+ }
+
+ @Override
+ public boolean isSearchMoreAvailable(SearchPhrase phrase) {
+ return phrase.getRadiusLevel() + SEARCH_RADIUS_INCREMENT < filter.getMaxSearchRadiusIndex();
+ }
}
public static class SearchHistoryAPI extends SearchBaseAPI {
diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
index 1fc00e95c2..461a163f00 100644
--- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
+++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java
@@ -25,6 +25,20 @@ import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
import net.osmand.NativeLibrary.RenderedObject;
import net.osmand.RenderingContext;
+import net.osmand.core.android.MapRendererView;
+import net.osmand.core.jni.AmenitySymbolsProvider.AmenitySymbolsGroup;
+import net.osmand.core.jni.AreaI;
+import net.osmand.core.jni.IBillboardMapSymbol;
+import net.osmand.core.jni.IMapRenderer.MapSymbolInformation;
+import net.osmand.core.jni.MapObject;
+import net.osmand.core.jni.MapObjectsSymbolsProvider.MapObjectSymbolsGroup;
+import net.osmand.core.jni.MapSymbolInformationList;
+import net.osmand.core.jni.MapSymbolsGroup.AdditionalBillboardSymbolInstanceParameters;
+import net.osmand.core.jni.ObfMapObject;
+import net.osmand.core.jni.PointI;
+import net.osmand.core.jni.QStringList;
+import net.osmand.core.jni.QStringStringHash;
+import net.osmand.core.jni.Utilities;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
@@ -46,6 +60,7 @@ import net.osmand.plus.render.MapRenderRepositories;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.plus.resources.TransportIndexRepository;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
+import net.osmand.plus.views.corenative.NativeCoreContext;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
@@ -56,6 +71,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import gnu.trove.list.array.TIntArrayList;
@@ -64,6 +80,7 @@ import static net.osmand.plus.mapcontextmenu.controllers.TransportStopController
public class ContextMenuLayer extends OsmandMapLayer {
//private static final Log LOG = PlatformUtil.getLog(ContextMenuLayer.class);
public static final int VIBRATE_SHORT = 100;
+ private static final int AMENITY_SEARCH_RADIUS = 50;
private OsmandMapTileView view;
@@ -579,8 +596,83 @@ public class ContextMenuLayer extends OsmandMapLayer {
= selectObjectsForContextMenu(tileBox, point, false, showUnknownLocation);
NativeOsmandLibrary nativeLib = NativeOsmandLibrary.getLoadedLibrary();
LatLon pointLatLon = tileBox.getLatLonFromPixel(point.x, point.y);
- if (nativeLib != null) {
- MapRenderRepositories maps = activity.getMyApplication().getResourceManager().getRenderer();
+ OsmandApplication app = activity.getMyApplication();
+ IContextMenuProvider poiMenuProvider = activity.getMapLayers().getPoiMapLayer();
+ if (app.getSettings().USE_OPENGL_RENDER.get() && NativeCoreContext.isInit()) {
+ MapRendererView rendererView = view.getMapRenderer();
+ if (rendererView != null) {
+ int delta = 20;
+ PointI tl = new PointI((int) point.x - delta, (int) point.y - delta);
+ PointI br = new PointI((int) point.x + delta, (int) point.y + delta);
+ MapSymbolInformationList symbols = rendererView.getSymbolsIn(new AreaI(tl, br), false);
+ for (int i = 0; i < symbols.size(); i++) {
+ MapSymbolInformation symbolInfo = symbols.get(i);
+ IBillboardMapSymbol billboardMapSymbol;
+ try {
+ billboardMapSymbol = IBillboardMapSymbol.dynamic_pointer_cast(symbolInfo.getMapSymbol());
+ } catch (Exception eBillboard) {
+ billboardMapSymbol = null;
+ }
+ if (billboardMapSymbol != null) {
+ double lat = Utilities.get31LatitudeY(billboardMapSymbol.getPosition31().getY());
+ double lon = Utilities.get31LongitudeX(billboardMapSymbol.getPosition31().getX());
+ objectLatLon = new LatLon(lat, lon);
+
+ AdditionalBillboardSymbolInstanceParameters billboardAdditionalParams;
+ try {
+ billboardAdditionalParams = AdditionalBillboardSymbolInstanceParameters
+ .dynamic_pointer_cast(symbolInfo.getInstanceParameters());
+ } catch (Exception eBillboardParams) {
+ billboardAdditionalParams = null;
+ }
+ if (billboardAdditionalParams != null && billboardAdditionalParams.getOverridesPosition31()) {
+ lat = Utilities.get31LatitudeY(billboardAdditionalParams.getPosition31().getY());
+ lon = Utilities.get31LongitudeX(billboardAdditionalParams.getPosition31().getX());
+ objectLatLon = new LatLon(lat, lon);
+ }
+
+ Amenity amenity = null;
+ net.osmand.core.jni.Amenity jniAmenity;
+ try {
+ jniAmenity = AmenitySymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()).getAmenity();
+ } catch (Exception eAmenity) {
+ jniAmenity = null;
+ }
+ if (jniAmenity != null) {
+ List names = getValues(jniAmenity.getLocalizedNames());
+ names.add(jniAmenity.getNativeName());
+ long id = jniAmenity.getId().getId().longValue() >> 7;
+ amenity = findAmenity(app, id, names, objectLatLon, AMENITY_SEARCH_RADIUS);
+ } else {
+ MapObject mapObject;
+ try {
+ mapObject = MapObjectSymbolsGroup.dynamic_cast(symbolInfo.getMapSymbol().getGroupPtr()).getMapObject();
+ } catch (Exception eMapObject) {
+ mapObject = null;
+ }
+ if (mapObject != null) {
+ ObfMapObject obfMapObject;
+ try {
+ obfMapObject = ObfMapObject.dynamic_pointer_cast(mapObject);
+ } catch (Exception eObfMapObject) {
+ obfMapObject = null;
+ }
+ if (obfMapObject != null) {
+ List names = getValues(obfMapObject.getCaptionsInAllLanguages());
+ names.add(obfMapObject.getCaptionInNativeLanguage());
+ long id = obfMapObject.getId().getId().longValue() >> 7;
+ amenity = findAmenity(app, id, names, objectLatLon, AMENITY_SEARCH_RADIUS);
+ }
+ }
+ }
+ if (amenity != null && isUnique(selectedObjects.keySet(), amenity)) {
+ selectedObjects.put(amenity, poiMenuProvider);
+ }
+ }
+ }
+ }
+ } else if (nativeLib != null) {
+ MapRenderRepositories maps = app.getResourceManager().getRenderer();
RenderingContext rc = maps.getVisibleRenderingContext();
RenderedObject[] renderedObjects = null;
if (rc != null && rc.zoom == tileBox.getZoom()) {
@@ -593,7 +685,7 @@ public class ContextMenuLayer extends OsmandMapLayer {
if (renderedObjects != null) {
int TILE_SIZE = 256;
double cosRotateTileSize = Math.cos(Math.toRadians(rc.rotate)) * TILE_SIZE;
- double sinRotateTileSize = Math.sin(Math.toRadians(rc.rotate)) * TILE_SIZE;
+ double sinRotateTileSize = Math.sin(Math.toRadians(rc.rotate)) * TILE_SIZE;
for (RenderedObject r : renderedObjects) {
double cx = r.getBbox().centerX();
double cy = r.getBbox().centerY();
@@ -605,7 +697,6 @@ public class ContextMenuLayer extends OsmandMapLayer {
double lon = MapUtils.get31LongitudeX(x31);
r.setLabelLatLon(new LatLon(lat, lon));
}
- IContextMenuProvider poiMenuProvider = activity.getMapLayers().getPoiMapLayer();
for (RenderedObject renderedObject : renderedObjects) {
if (renderedObject.getX() != null && renderedObject.getX().size() == 1
&& renderedObject.getY() != null && renderedObject.getY().size() == 1) {
@@ -620,38 +711,24 @@ public class ContextMenuLayer extends OsmandMapLayer {
names.add(renderedObject.getName());
}
for (Entry entry : renderedObject.getTags().entrySet()) {
- if (entry.getKey().startsWith("name:") && !entry.getValue().equals("")) {
- names.add(entry.getValue());
- }
- if (entry.getKey().equals("name") && !entry.getValue().equals("")) {
- names.add(entry.getValue());
+ String key = entry.getKey();
+ String value = entry.getValue();
+ if ((key.startsWith("name:") || key.equals("name")) && !value.isEmpty()) {
+ names.add(value);
}
}
LatLon searchLatLon = objectLatLon;
if (searchLatLon == null) {
searchLatLon = pointLatLon;
}
- Amenity amenity = findAmenity(activity.getMyApplication(), renderedObject.getId() >> 7, names, searchLatLon, 50);
+ Amenity amenity = findAmenity(app, renderedObject.getId() >> 7, names, searchLatLon, AMENITY_SEARCH_RADIUS);
if (amenity != null) {
if (renderedObject.getX() != null && renderedObject.getX().size() > 1
&& renderedObject.getY() != null && renderedObject.getY().size() > 1) {
amenity.getX().addAll(renderedObject.getX());
amenity.getY().addAll(renderedObject.getY());
}
- boolean exists = false;
- for (Object o : selectedObjects.keySet()) {
- if (o instanceof Amenity && ((Amenity) o).compareTo(amenity) == 0) {
- exists = true;
- break;
- } else if (o instanceof TransportStop) {
- TransportStop transportStop = (TransportStop) o;
- if (transportStop.getName().startsWith(amenity.getName())) {
- exists = true;
- break;
- }
- }
- }
- if (!exists) {
+ if (isUnique(selectedObjects.keySet(), amenity)) {
selectedObjects.put(amenity, poiMenuProvider);
}
continue;
@@ -711,6 +788,28 @@ public class ContextMenuLayer extends OsmandMapLayer {
return false;
}
+ private List getValues(@Nullable QStringStringHash set) {
+ List res = new ArrayList<>();
+ if (set != null) {
+ QStringList keys = set.keys();
+ for (int i = 0; i < keys.size(); i++) {
+ res.add(set.get(keys.get(i)));
+ }
+ }
+ return res;
+ }
+
+ private boolean isUnique(@NonNull Set