Merge branch 'master' of ssh://github.com/osmandapp/Osmand into RefactorTelegram

This commit is contained in:
Chumva 2018-10-11 14:44:12 +03:00
commit 82138587fc
43 changed files with 736 additions and 189 deletions

View file

@ -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;
}

View file

@ -5,10 +5,13 @@ import java.util.Map;
public class CommonWords {
private static Map<String, Integer> commonWordsDictionary = new LinkedHashMap<>();
private static Map<String, Integer> 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
@ -18,9 +21,14 @@ public class CommonWords {
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");

View file

@ -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;
}
}

View file

@ -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<BinaryMapIndexReader> 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<String> ids = new HashSet<String>();
SearchRequest<Amenity> 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<Amenity> getResultMatcher(final SearchPhrase phrase, final SearchResultMatcher resultMatcher,
final String customName, final BinaryMapIndexReader selected,
final Set<String> 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;

View file

@ -33,6 +33,7 @@ public class SearchPhrase {
private List<String> unknownWords = new ArrayList<>();
private List<NameStringMatcher> 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();
@ -214,6 +216,10 @@ public class SearchPhrase {
return unknownSearchWordTrim;
}
public String getRawUnknownSearchPhrase() {
return rawUnknownSearchPhrase;
}
public String getUnknownSearchPhrase() {
return unknownSearchPhrase;
}

View file

@ -20,7 +20,7 @@ public class SearchResult {
public SearchResult parentSearchResult;
public Collection<String> 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();
}

View file

@ -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) {
addArray(months, monthNames, b);
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;
}
boolean allDays = true;
for (int i = 0; i < dayMonths.length; i++) {
if (!dayMonths[i]) {
allDays = false;
if (!dayMonths[month][day]) {
excludedMonthEnd = prevMonth;
excludedDayEnd = prevDay;
break;
}
prevDay = day;
}
if (excludedDayEnd != -1) {
break;
}
}
if (!allDays) {
addArray(dayMonths, null, b);
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);
}
// 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,15 +1568,25 @@ 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() {
if (parent != null) {
return parent.text + " [" + parent.type + "] (" + text + " [" + type + "]) ";
} else {
return text + " [" + type + "] ";
}
}
}
public static void parseRuleV2(String r, int sequenceIndex, List<OpeningHoursRule> rules) {
String comment = null;
@ -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<Token> tokens, List<OpeningHoursRule> rules) {
// order MONTH MONTH_DAY DAY_WEEK HOUR_MINUTE OPEN_OFF
TokenType currentParse = TokenType.TOKEN_UNKNOWN;
TokenType currentParseParent = TokenType.TOKEN_UNKNOWN;
List<Token[]> listOfPairs = new ArrayList<>();
Set<TokenType> 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,23 +1733,49 @@ 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;
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 {
// overflow
for (int j = pair[0].mainNumber; j < array.length; j++) {
array[j] = true;
for (int month = firstMonthToken.mainNumber + 1; month < 12; month++) {
Arrays.fill(basic.getDayMonths(month), true);
}
for (int j = 0; j <= pair[1].mainNumber; j++) {
array[j] = 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) {
if (pair[0].mainNumber == 0) {
@ -1641,10 +1786,16 @@ public class OpeningHoursParser {
basic.easter = true;
}
} else if (pair[0].mainNumber >= 0) {
Token firstMonthToken = pair[0].parent;
if (tokenDayMonth && firstMonthToken != null) {
array = basic.getDayMonths(firstMonthToken.mainNumber);
}
if (array != null) {
array[pair[0].mainNumber] = true;
}
}
}
}
} else if (currentParse == TokenType.TOKEN_HOUR_MINUTES) {
for (Token[] pair : listOfPairs) {
if (pair[0] != null && pair[1] != null) {
@ -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];
@ -1683,19 +1839,46 @@ public class OpeningHoursParser {
} else if (t.type.ord() == currentParse.ord()) {
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)) {
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) &&
!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)) {

View file

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -3962,4 +3962,6 @@
<string name="poi_license_classes">Licensklasser</string>
<string name="poi_hill">Bakke</string>
</resources>

View file

@ -2536,7 +2536,7 @@ Repræsenterer område: %1$s x %2$s</string>
<string name="quick_action_map_underlay_switch">Kortunderlejring ændret til \"%s\".</string>
<string name="quick_action_page_list_descr">Tryk på genvejsknappen gennemløber nedenstående liste.</string>
<string name="auto_split_recording_title">Opdel automatisk optagelser efter et ophold</string>
<string name="auto_split_recording_descr">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.</string>
<string name="auto_split_recording_descr">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.</string>
<string name="rendering_attr_depthContours_description">Vis dybdekonturer og -punkter.</string>
<string name="rendering_attr_depthContours_name">Havdybdekonturer</string>
@ -3206,4 +3206,12 @@ Repræsenterer område: %1$s x %2$s</string>
<string name="ask_for_location_permission">Giv OsmAnd tilladelse til placering for at fortsætte.</string>
<string name="rendering_value_black_name">Sort</string>
<string name="more_transport_on_stop_hint">Der er andre transportmidler ved dette stop.</string>
<string name="markers_remove_dialog_msg">Slet kortmarkør \'%s\'\?</string>
<string name="edit_map_marker">Rediger kortmarkør</string>
<string name="third_party_application">Tredjepartsprogram</string>
<string name="search_street">Søg efter gade</string>
<string name="start_search_from_city">Start søgning fra byen</string>
<string name="shared_string_restore">Gendan</string>
<string name="keep_passed_markers_descr">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.</string>
<string name="keep_passed_markers">Behold passerede markører på kortet</string>
</resources>

View file

@ -840,9 +840,9 @@
<string name="poi_piste_downhill">Skivojo alpa (malsuprenira)</string>
<string name="poi_piste_nordic">Skivojo nordia (skikurada)</string>
<string name="poi_piste_skitour">Skivojo ski-ekskursuma</string>
<string name="poi_piste_hike">Skivojo skikurada</string>
<string name="poi_piste_sleigh">Skivojo glitveturila</string>
<string name="poi_piste_sled">Skivojo glitveturila (tirata de hundoj)</string>
<string name="poi_piste_hike">Skivojo marŝada</string>
<string name="poi_piste_sleigh">Skivojo glitveturila (tirata de hundoj)</string>
<string name="poi_piste_sled">Skivojo glitveturila</string>
<string name="poi_piste_snow_park">Skivojo neĝ-parka</string>
<string name="poi_piste_playground">Skivojo infanludeja</string>
<string name="poi_piste_ice_skate">Skivojo glitkurada</string>

View file

@ -3870,4 +3870,6 @@
<string name="poi_license_classes">Lizentzia klaseak</string>
<string name="poi_hill">Muinoa</string>
</resources>

View file

@ -3144,7 +3144,13 @@ Area honi dagokio: %1$s x %2$s</string>
\n</string>
<string name="commiting_way">Bidea betetzen…</string>
<string name="test_voice_desrc">Sakatu botoi bat eta entzun dagokion ahots-deskripzioa falta diren edo gaizki dauden deskripzioan antzemateko.</string>
<string name="release_3_2_pre">• Karaktere mapa ez latinoetan gertatzen zen kraskatzea konponduta
<string name="release_3_2_pre">• 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
@ -3160,4 +3166,7 @@ Area honi dagokio: %1$s x %2$s</string>
<string name="keep_passed_markers_descr">Gogokoen talde gisa gehitutako markatzaileak edo pasatutako gisa markatutako GPX bide-puntuak mapan mantenduko dira. Taldea aktibo ez badago, markatzaileak mapatik desagertuko dira.</string>
<string name="keep_passed_markers">Mantendu pasatutako markatzaileak mapan</string>
<string name="more_transport_on_stop_hint">Garraio gehiago daude geldiune honetan.</string>
<string name="markers_remove_dialog_msg">Ezabatu \'%s\' mapa-markatzailea\?</string>
<string name="edit_map_marker">Editatu mapa-markatzailea</string>
<string name="third_party_application">Hirugarrengoen aplikazioa</string>
</resources>

View file

@ -2202,4 +2202,65 @@
<string name="poi_trade_agricultural_supplies">אספקה חקלאית</string>
<string name="poi_trade_tile">ציוד ריצוף</string>
<string name="poi_smoking_separated">בחדר נפרד</string>
<string name="poi_smoking_isolated">בחדר מבודד</string>
<string name="poi_smoking_dedicated">מוקדש למעשנים</string>
<string name="poi_toll_yes">אגרה</string>
<string name="poi_toll_no">ללא אגרה</string>
<string name="poi_toll_hgv_yes">אגרה למשאיות</string>
<string name="poi_tactile_paving_yes">כן</string>
<string name="poi_traffic_signals_sound_yes">כן</string>
<string name="poi_traffic_signals_sound_no">לא</string>
<string name="poi_traffic_signals_sound_walk">רק כאשר מותר לחצות</string>
<string name="poi_rescue_station">תחנת הצלה</string>
<string name="poi_services">אזור שירות</string>
<string name="poi_mini_roundabout">כיכר מזערית</string>
<string name="poi_internet_access_type_wlan">רשת אלחוטית</string>
<string name="poi_internet_access_type_terminal">מסוף</string>
<string name="poi_internet_access_type_wired">חיבור קווי</string>
<string name="poi_internet_access_type_public">סוג הגישה לאינטרנט: ציבורית</string>
<string name="poi_internet_access_type_service">סוג הגישה לאינטרנט: שירות</string>
<string name="poi_internet_access_type_no">אין גישה לאינטרנט</string>
<string name="poi_internet_access_type_yes">יש גישה לאינטרנט</string>
<string name="poi_maxwidth">רוחב מרבי</string>
<string name="poi_iata">קוד IATA</string>
<string name="poi_icao">קוד ICAO</string>
<string name="poi_faa">קוד FAA</string>
<string name="poi_artwork_type_sculpture">סוג יצירת האומנות: מוצג תלת ממדי</string>
<string name="poi_artwork_type_statue">סוג יצירת האומנות: פיסול</string>
<string name="poi_artwork_type_mural">סוג יצירת האומנות: ציור קיר</string>
<string name="poi_artwork_type_architecture">סוג יצירת האומנות: אדריכלות</string>
<string name="poi_artwork_type_painting">סוג יצירת האומנות: ציור</string>
<string name="poi_artwork_type_stone">סוג יצירת האומנות: אבן</string>
<string name="poi_artwork_type_bust">סוג יצירת האומנות: פסל ראש וכתפיים (פרוטומה/בוסטה)</string>
<string name="poi_artwork_type_installation">סוג יצירת האומנות: מיצב</string>
<string name="poi_artwork_type_mosaic">סוג יצירת האומנות: פסיפס</string>
<string name="poi_artwork_type_relief">סוג יצירת האומנות: תבליט</string>
<string name="poi_artwork_type_graffiti">סוג יצירת האומנות: גרפיטי</string>
<string name="poi_artwork_type_fountain">סוג יצירת האומנות: מזרקה</string>
<string name="poi_width">רוחב</string>
<string name="poi_architect_name">אדריכל/ית</string>
<string name="poi_architecture_modern">אדריכלות: מודרנית</string>
<string name="poi_architecture_stalinist_neoclassicism">אדריכלות: נאוקלסיציזם סטליניסטי</string>
<string name="poi_aerodrome_type_international">בינלאומי</string>
<string name="poi_aerodrome_type_regional">אזורי</string>
<string name="poi_aerodrome_type_public">ציבורי</string>
<string name="poi_aerodrome_type_military">צבאי</string>
<string name="poi_aerodrome_type_military_public">צבאי/ציבורי</string>
<string name="poi_aerodrome_type_private">פרטי</string>
<string name="poi_ventilation_shaft">פיר אוורור</string>
<string name="poi_license_classes">סוגי רישיונות נהיגה</string>
<string name="poi_hill">גבעה</string>
</resources>

View file

@ -741,8 +741,8 @@
<string name="poi_payment_type">Tipo di pagamento</string>
<string name="poi_payment_fuel_type">Carte carburante</string>
<string name="poi_additional_type">Ulteriori</string>
<string name="poi_internet_access_type">Tipo di accesso Internet</string>
<string name="poi_bicycle_service">Servizio biciclette</string>
<string name="poi_internet_access_type">Tipo di accesso a internet</string>
<string name="poi_bicycle_service">Servizio per biciclette</string>
<string name="poi_clothes_type">Tipo</string>
<string name="poi_shoes_type">Tipo</string>
<string name="poi_fire_hydrant_type">Tipo</string>
@ -1277,7 +1277,7 @@
<string name="poi_archery">Tiro con l\'arco</string>
<string name="poi_club_ethnic">Club etnico</string>
<string name="poi_dyke">Frangiflutti</string>
<string name="poi_vending_type">Tipo vendita</string>
<string name="poi_vending_type">Tipo di vendita</string>
<string name="poi_scout_camp">Campo scout</string>
<string name="poi_drive_through">Guidare attraverso</string>
<string name="poi_charity">Negozio di beneficenza</string>

View file

@ -2390,7 +2390,7 @@ Se ami OsmAnd e OSM e vuoi sostenerli, questo è un modo perfetto per farlo.</st
<string name="route_calculation">Calcolo del percorso</string>
<string name="gpx_no_tracks_title">Non hai ancora nessun file GPX</string>
<string name="gpx_no_tracks_title_folder">È inoltre possibile aggiungere file GPX alla cartella</string>
<string name="gpx_add_track">Aggiungi traccia</string>
<string name="gpx_add_track">Aggiungi altri…</string>
<string name="gpx_appearance">Aspetto</string>
@ -3079,12 +3079,12 @@ Rappresenta l\'area: %1$s x %2$s</string>
\n"</string>
<string name="quick_action_edit_actions">Modifica le azioni</string>
<string name="error_notification_desc">Per favore invia una schermata di questa notifica a support@osmand.net</string>
<string name="poi_cannot_be_found">Il nodo o il percorso non è stato trovato.</string>
<string name="search_no_results_feedback">Nessun risultato di ricerca?
\nDacci un ritorno</string>
<string name="poi_cannot_be_found">Non è possibile trovare il nodo o il percorso.</string>
<string name="search_no_results_feedback">Nessun risultato\?
\nDacci un feedback</string>
<string name="release_3_1">• 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</string>
\n
\n</string>
<string name="commiting_way">Sottoponi la via…</string>
<string name="increase_search_radius_to">Incrementa il raggio di ricerca a %1$s</string>
<string name="send_search_query_description">Invieremo le tue ricerche: <b>\"%1$s\"</b>, e la tua localizzazione.<br/><br/> Non raccogliamo informazioni personali, abbiamo solo bisogno dei dati delle ricerche per migliorare l\'algoritmo di ricerca.<br/></string>
<string name="increase_search_radius_to">Aumenta il raggio di ricerca a %1$s</string>
<string name="send_search_query_description">Invieremo la tua ricerca <b>\"%1$s\"</b> oltre alla tua localizzazione.<br/><br/> Non raccogliamo informazioni personali, abbiamo solo bisogno dei dati delle ricerche per migliorare l\'algoritmo di ricerca.<br/></string>
<string name="send_search_query">Inviare i dati delle ricerche?</string>
<string name="shared_string_world">Mondo</string>
<string name="point_deleted">Punto %1$s eliminato</string>
@ -3108,21 +3108,30 @@ Rappresenta l\'area: %1$s x %2$s</string>
<string name="coord_input_save_as_track">Salva come traccia</string>
<string name="coord_input_save_as_track_descr">Hai aggiunto %1$s punti. Digita il nome del file e tappa su \"Salva\".</string>
<string name="test_voice_desrc">Tap sul pulsante e ascolta l\'avviso vocale corrispondente per identificare gli avvisi errati o mancanti</string>
<string name="release_3_2_pre">• Corretto l\'arresto in avvio con le mappe non latine
<string name="release_3_2_pre">• 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
\n • Misuratore di distanze: aggiunto il bottone Misura la distanza alle azioni nel menù laterale
\n</string>
<string name="ask_for_location_permission">Per favore dai OsmAnd il permesso alla localizzazione per continuare.</string>
<string name="ask_for_location_permission">Per favore concedi il permesso a OsmAnd di accedere alla geolocalizzazione per continuare.</string>
<string name="thank_you_for_feedback">Grazie per il feedback</string>
<string name="search_street">Ricerca per strada</string>
<string name="search_street">Ricerca strada</string>
<string name="start_search_from_city">Inizia la ricerca dalla città</string>
<string name="shared_string_restore">Ripristina</string>
<string name="keep_passed_markers">Tenere passati marcatori sulla mappa</string>
<string name="keep_passed_markers">Tenere i marcatori superati sulla mappa</string>
<string name="more_transport_on_stop_hint">C\'è più trasporto su questa fermata.</string>
<string name="keep_passed_markers_descr">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.</string>
<string name="keep_passed_markers_descr">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.</string>
<string name="rendering_value_black_name">Nero</string>
<string name="markers_remove_dialog_msg">Eliminare il marcatore \'%s\'\?</string>
<string name="edit_map_marker">Modifica marcatore</string>
<string name="third_party_application">Applicazione di terze parti</string>
</resources>

View file

@ -644,8 +644,8 @@
<string name="poi_chalet">Domek letniskowy</string>
<string name="poi_apartment">Apartament</string>
<string name="poi_piste_hike">Trasa piesza</string>
<string name="poi_piste_sleigh">Trasa saneczkarska</string>
<string name="poi_piste_sled">Trasa saneczkarska (zaprzęgi)</string>
<string name="poi_piste_sleigh">Trasa saneczkarska (zaprzęgi)</string>
<string name="poi_piste_sled">Trasa saneczkarska</string>
<string name="poi_piste_playground">Trasa dla dzieci</string>
<string name="poi_stripclub">Klub ze striptizem</string>
<string name="poi_beach_resort">Ośrodek nadmorski</string>

View file

@ -2235,7 +2235,7 @@ Pôr do Sol: %2$s</string>
<string name="routing_attr_avoid_ice_roads_fords_name">Evitar estradas de gelo, vaus</string>
<string name="routing_attr_avoid_ice_roads_fords_description">Evitar estradas de gelo e vaus.</string>
<string name="map_orientation_change_in_accordance_with_speed">Limite para orientação do mapa</string>
<string name="quick_action_show_navigation_finish_dialog">Mostrar diálogo \'Navegação finalizada\'</string>
<string name="quick_action_show_navigation_finish_dialog">Mostrar \'Navegação finalizada\'</string>
<string name="mapillary_menu_title_tile_cache">Cache de quadrícula</string>
<string name="map_widget_ruler_control">Régua de raio</string>
<string name="show_from_zoom_level">Exibir a partir do nível de zoom</string>

View file

@ -100,7 +100,7 @@
<string name="shared_string_start_time">Отправление</string>
<string name="shared_string_end_time">Прибытие</string>
<string name="shared_string_color">Цвет</string>
<string name="select_gpx_folder">Выберите папку для GPX файла</string>
<string name="select_gpx_folder">Выберите папку для файла GPX</string>
<string name="shared_string_move">Переместить</string>
<string name="shared_string_gpx_tracks">Треки</string>
<string name="altitude_descent">Спуск</string>
@ -168,8 +168,8 @@
<string name="upload_poi">Выгрузить POI</string>
<string name="route_calculation">Построение маршрута</string>
<string name="gpx_no_tracks_title">У вас пока нет треков</string>
<string name="gpx_no_tracks_title_folder">Вы также можете добавить треки в папку</string>
<string name="gpx_no_tracks_title">У вас пока нет файлов GPX</string>
<string name="gpx_no_tracks_title_folder">Вы также можете добавить файлы GPX в папку</string>
<string name="gpx_add_track">Добавить</string>
<string name="gpx_appearance">Вид</string>
@ -215,7 +215,7 @@
<string name="save_filter">Сохранить фильтр</string>
<string name="delete_filter">Удалить фильтр</string>
<string name="new_filter">Новый фильтр</string>
<string name="number_of_gpx_files_selected_pattern">%s GPX трека(ов) выбрано</string>
<string name="number_of_gpx_files_selected_pattern">%s файла(ов) GPX выбрано</string>
<string name="change_markers_position">Изменить положение маркера</string>
<string name="current_track">Текущий путь</string>
<string name="use_osm_live_routing">Навигация OsmAnd Live</string>
@ -365,7 +365,7 @@
<string name="plugins_screen">Плагины</string>
<string name="prefs_plugins_descr">Плагины активируют дополнительные возможности приложения.</string>
<string name="prefs_plugins">Плагины</string>
<string name="osm_editing_plugin_description">С помощью этого плагина OsmAnd может быть использован для улучшения OSM через создание или изменение объектов OSM POI, открытие или комментирование OSM заметок, а также отправку записанные GPX файлов. OSM развивается обществом, глобальный проект создания карты общей собственности. Для получения дополнительной информации, пожалуйста, обращайтесь на https://openstreetmap.org. Активное участие ценится, и взносы могут быть сделаны непосредственно через OsmAnd, если вы укажете свои учетные данные OSM в настройках.</string>
<string name="osm_editing_plugin_description">С помощью этого плагина OsmAnd может быть использован для улучшения OSM через создание или изменение объектов OSM POI, открытие или комментирование OSM заметок, а также отправку записанных файлов GPX. OSM развивается обществом, глобальный проект создания карты общей собственности. Для получения дополнительной информации, пожалуйста, обращайтесь на https://openstreetmap.org. Активное участие ценится, и взносы могут быть сделаны непосредственно через OsmAnd, если вы укажете свои учетные данные OSM в настройках.</string>
<string name="vector_maps_may_display_faster_on_some_devices">Векторные карты могут отображаться быстрее. Поддерживается не всеми устройствами.</string>
<string name="play_commands_of_currently_selected_voice">Воспроизвести команды выбранным голосом</string>
<string name="debugging_and_development">Отладка и разработка</string>
@ -837,8 +837,8 @@
<string name="auto_zoom_map_descr">Автоматически изменять масштаб карты при изменении скорости (пока карта синхронизирована с текущим положением).</string>
<string name="auto_zoom_map">Автомасштаб</string>
<string name="additional_settings">Дополнительные настройки</string>
<string name="save_current_track_descr">Сохранить текущий трек на SD-карту сейчас.</string>
<string name="save_current_track">Сохранить текущий трек GPX</string>
<string name="save_current_track_descr">Сохранить текущий трек как файл GPX.</string>
<string name="save_current_track">Сохранить текущий трек</string>
<string name="save_track_interval_descr">Выберите интервал для записи трека во время навигации.</string>
<string name="save_track_interval">Интервал записи во время навигации</string>
<string name="save_track_to_gpx_descrp">Во время навигации треки GPX будут автоматически сохранены в папку с треками.</string>
@ -1679,7 +1679,7 @@
<string name="duration">Продолжительность</string>
<string name="save_track_to_gpx_globally">Запись трека в файл GPX</string>
<string name="save_track_interval_globally">Интервал записи</string>
<string name="save_track_to_gpx_globally_descr">Общая запись местоположения в файл GPX может быть включена или выключена с помощью виджета записи GPX на экране карты.</string>
<string name="save_track_to_gpx_globally_descr">Ведение записи местоположения в файл GPX можно включить или выключить с помощью виджета записи GPX на экране карты.</string>
<string name="record_plugin_description">"Плагин активирует функции для записи и сохранения ваших треков вручную нажатием на виджет записи GPX на экране карты, или также автоматически записывает все ваши маршруты навигации в файл GPX.
\n
\nЗаписанными треками можно поделиться с вашими друзьями или использовать их для вклада в OSM. Спортсмены могут использовать записанные треки для контроля за тренировками. Некоторый базовый анализ треков может быть выполнен непосредственно в OsmAnd, например, время прохождения круга, средняя скорость и т.д., треки, конечно, позднее также могут быть проанализированы в специальных инструментах анализа сторонних производителей."</string>
@ -1814,7 +1814,7 @@
<string name="shared_string_select_all">Выбрать все</string>
<string name="shared_string_clear">Очистить</string>
<string name="shared_string_save">Сохранить</string>
<string name="shared_string_save_as_gpx">Сохранить как новый GPX трек</string>
<string name="shared_string_save_as_gpx">Сохранить как новый файл GPX</string>
<string name="shared_string_rename">Переименовать</string>
<string name="shared_string_delete">Удалить</string>
<string name="shared_string_delete_all">Удалить все</string>
@ -2056,7 +2056,7 @@
<string name="show_on_start">Показывать при запуске</string>
<string name="are_you_sure">Вы уверены?</string>
<string name="unsaved_changes_will_be_lost">Все несохраненные изменения будут потеряны. Продолжить?</string>
<string name="simulate_your_location_descr">Моделировать ваше местоположение, используя рассчитанный маршрут или записанный GPX.</string>
<string name="simulate_your_location_descr">Моделировать ваше местоположение, используя рассчитанный маршрут или записанный трек GPX.</string>
<string name="simulate_your_location_stop_descr">Остановить моделирование своего местоположения.</string>
<string name="favorite_category_add_new">Добавить новую</string>
<string name="favorite_category_select">Выберите категорию</string>
@ -2150,8 +2150,8 @@
<string name="route_duration">Время:</string>
<string name="access_from_map_description">Кнопка меню открывает панель управления, а не меню</string>
<string name="access_from_map">Доступ с карты</string>
<string name="context_menu_item_delete_waypoint">Удалить точку GPX?</string>
<string name="context_menu_item_edit_waypoint">Редактировать точку GPX</string>
<string name="context_menu_item_delete_waypoint">Удалить путевую точку GPX\?</string>
<string name="context_menu_item_edit_waypoint">Редактировать путевую точку GPX</string>
<string name="routing_attr_avoid_stairs_name">Избегать лестниц</string>
<string name="routing_attr_avoid_stairs_description">Избегать лестниц</string>
<string name="routing_attr_avoid_borders_name">Избегать пересечения границы</string>
@ -2346,7 +2346,7 @@
<string name="first_usage_greeting">Прокладывайте маршруты и открывайте новые для себя места без подключения к Интернету</string>
<string name="allow_access_location">Разрешить доступ к местоположению</string>
<string name="give_permission">Дать разрешение</string>
<string name="storage_place_description">OsmAnd будет хранить данные (карты, маршруты и пр.) в %1$s.</string>
<string name="storage_place_description">Хранилище данных OsmAnd (для карт, файлов GPX и пр.): %1$s.</string>
<string name="storage_free_space">Свободное место</string>
<string name="search_location">Определение местоположения…</string>
<string name="no_inet_connection_desc_map">Требуется загрузить карты</string>
@ -2464,7 +2464,7 @@
<string name="distance_moving">Откорректированное расстояние</string>
<string name="improve_coverage_install_mapillary_desc">Установите Mapillary, чтобы добавить одну или несколько фотографий к этому месту на карте.</string>
<string name="route_altitude">Высота маршрута</string>
<string name="enter_gpx_name">Имя GPX файла:</string>
<string name="enter_gpx_name">Имя файла GPX:</string>
<string name="show_on_map_after_saving">Показать на карте после сохранения</string>
<string name="measurement_tool_action_bar">Просмотрите карту и добавьте точки</string>
<string name="measurement_tool">Измерить расстояние</string>
@ -2502,7 +2502,7 @@
<string name="this_year">В этом году</string>
<string name="plan_route">План маршрута</string>
<string name="coordinate_input">Ввод координат</string>
<string name="marker_save_as_track">Сохранить как GPX файл</string>
<string name="marker_save_as_track">Сохранить как файл GPX</string>
<string name="move_to_history">Переместить в историю</string>
<string name="group_will_be_removed_after_restart">Группа будет выключена при следующем запуске приложения.</string>
<string name="show_arrows_on_the_map">Показывать стрелки на карте</string>
@ -2517,7 +2517,7 @@
<string name="my_location">Мое местоположение</string>
<string name="shared_string_finish">Финиш</string>
<string name="shared_string_sort">Сортировать</string>
<string name="marker_save_as_track_descr">Экспорт маркеров в следующий GPX файл:</string>
<string name="marker_save_as_track_descr">Экспорт маркеров в следующий файл GPX:</string>
<string name="shared_string_markers">Маркеры</string>
<string name="osn_modify_dialog_title">Изменить заметку</string>
<string name="context_menu_item_modify_note">Изменить заметку OSM</string>
@ -2531,8 +2531,8 @@
<string name="map_orientation_change_in_accordance_with_speed">Смена ориентации карты</string>
<string name="map_orientation_change_in_accordance_with_speed_descr">Выберите ниже скорость, при которой переключается ориентация карты с \"По направлению движения\" на \"По направлению компаса\".</string>
<string name="all_markers_moved_to_history">Все маркеры перемещены в историю</string>
<string name="marker_moved_to_history">Маркер карты перемещен в историю</string>
<string name="marker_moved_to_active">Маркер карты перемещен в действующие</string>
<string name="marker_moved_to_history">Маркер перемещен в историю</string>
<string name="marker_moved_to_active">Маркер перемещен в действующие</string>
<string name="show_direction">Указатель расстояния</string>
@ -2590,7 +2590,7 @@
<string name="add_favourites_group_to_markers_descr">Выберите категорию избранных для добавления к маркерам.</string>
<string name="favourites_group">Категория избранных</string>
<string name="add_group">Добавить группу</string>
<string name="add_group_descr">Импортировать группу из избранных или GPX путевых точек.</string>
<string name="add_group_descr">Импортировать группу из избранных или путевых точек GPX.</string>
<string name="empty_state_markers_active">Создайте маркеры карт!</string>
<string name="empty_state_markers_active_desc">Длинное или короткое нажатие на нужное место, а затем на флажок маркера.</string>
<string name="empty_state_markers_groups">Импорт групп</string>
@ -2618,7 +2618,7 @@
<string name="show_number_pad">Показать цифровую панель</string>
<string name="tap_on_map_to_hide_interface_descr">Нажатие на карте переключает кнопки управления и виджеты.</string>
<string name="import_gpx_file_description">могут быть импортированы как избранные точки или как GPX файл.</string>
<string name="import_gpx_file_description">могут быть импортированы как избранные точки или как файл GPX.</string>
<string name="shared_string_more_without_dots">Больше</string>
<string name="import_as_gpx">Импортировать как файл GPX</string>
<string name="import_as_favorites">Импортировать как избранные</string>
@ -2813,7 +2813,7 @@
<string name="switch_osm_notes_visibility_desc">Показать/скрыть заметки OSM на карте.</string>
<string name="gpx_file_desc">GPX - подходит для экспорта в JOSM и другие OSM редакторы.</string>
<string name="osc_file_desc">OSC - подходит для экспорта в OpenStreetMap.</string>
<string name="shared_string_gpx_file">GPX файл</string>
<string name="shared_string_gpx_file">Файл GPX</string>
<string name="osc_file">OSC файл</string>
<string name="choose_file_type">Выберите тип файла</string>
<string name="osm_edits_export_desc">Выберите тип экспорта: заметки OSM, POI или оба.</string>
@ -2993,7 +2993,10 @@
<string name="search_street">Поиск улицы</string>
<string name="start_search_from_city">Начать поиск с города</string>
<string name="shared_string_restore">Восстановить</string>
<string name="keep_passed_markers_descr">Маркеры, добавленные как группа избранных или GPX путевых точек и отмеченные как пройденные, останутся на карте. Если группа не активна, маркеры исчезнут с карты.</string>
<string name="keep_passed_markers_descr">Маркеры, добавленные как группа избранных или путевых точек GPX и отмеченные как пройденные, останутся на карте. Если группа не активна, маркеры исчезнут с карты.</string>
<string name="keep_passed_markers">Оставить пройденные маркеры на карте</string>
<string name="more_transport_on_stop_hint">На этой остановке есть другие транспортные средства.</string>
<string name="markers_remove_dialog_msg">Удалить маркер \'%s\'\?</string>
<string name="edit_map_marker">Редактировать маркер</string>
<string name="third_party_application">Стороннее приложение</string>
</resources>

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><resources>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="search_button">Poišči</string>
<string name="search_activity">Iskanje podatkov</string>
@ -364,7 +365,7 @@ Sorazmerna velikost pomnilnika je %4$s MB (omejitev na androidu je %5$s MB, na d
<string name="osmand_parking_event">Odpeljite vozilo s parkirišča</string>
<string name="osmand_parking_warning_text">Obvestilo, da odpeljite vozilo s parkirišča, je bilo dodano v koledar. Ostalo bo zapisano, dokler ga ne izbrišete ročno.</string>
<string name="osmand_parking_time_limit_title">Nastavi časovno omejitev parkiranja</string>
<string name="osmand_parking_delete_confirm">Ali želite izbrisati označbo mesta, kjer je vozilo parkirano?</string>
<string name="osmand_parking_delete_confirm">Ali želite izbrisati označbo mesta parkiranja\?</string>
<string name="osmand_parking_delete">Izbriši označbo mesta parkiranja</string>
<string name="osmand_parking_choose_type">Izbor vrste parkiranja</string>
<string name="osmand_parking_lim_text">Časovno omejeno</string>
@ -2129,7 +2130,7 @@ Omogoča tudi dodajanje opomb v koledar za prikaz opomnikov ob daljših časih p
<string name="show_map_markers_description">Omogoči možnosti označb zemljevida.</string>
<string name="clear_active_markers_q">Ali želite odstraniti vse dejavne označbe?</string>
<string name="clear_markers_history_q">Ali res želite počistiti zgodovino označbe?</string>
<string name="clear_markers_history_q">Ali želite počistiti zgodovino označb\?</string>
<string name="active_markers">Dejavne označbe</string>
<string name="map_markers">Označbe zemljevida</string>
<string name="map_marker">Označba zemljevida</string>
@ -2440,7 +2441,7 @@ Koda predstavlja območje: %1$s x %2$s</string>
<string name="auto_split_recording_title">Samodejno razdeli beleženje po vmesnih točkah</string>
<string name="auto_split_recording_descr">Zač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.</string>
<string name="quick_action_add_marker_descr">S pritiskom na gumb dejanja bo dodana označba na zemljevid na trenutno sredinsko točko na zaslonu.</string>
<string name="quick_action_add_marker_descr">S pritiskom na gumb dejanja bo dodana označba na trenutno sredinsko točko.</string>
<string name="quick_action_add_gpx_descr">S pritiskom na gumb dejanja bo dodana vmesna točka GPX na trenutno sredinsko točko na zaslonu.</string>
<string name="quick_action_take_audio_note_descr">S pritiskom na gumb dejanja bo dodano zvočno sporočilo na trenutno sredinsko točko na zaslonu.</string>
<string name="quick_action_take_video_note_descr">S pritiskom na gumb dejanja bo dodano video sporočilo na trenutno sredinsko točko na zaslonu.</string>
@ -2987,4 +2988,12 @@ Koda predstavlja območje: %1$s x %2$s</string>
<string name="wiki_article_search_text">Iskanje pripadajočega prispevka na Wikipediji</string>
<string name="wiki_article_not_found">Prispevka ni mogoče najti</string>
<string name="how_to_open_wiki_title">Kako odpreti prispevek na Wikipediji?</string>
<string name="markers_remove_dialog_msg">Ali res želite izbrisati označbo »%s«\'\?</string>
<string name="edit_map_marker">Uredi označbo zemljevida</string>
<string name="third_party_application">Programi tretjih oseb</string>
<string name="search_street">Iskanje ulice</string>
<string name="start_search_from_city">Začni z iskanjem mesta</string>
<string name="shared_string_restore">Obnovi</string>
<string name="thank_you_for_feedback">Zahvaljujemo se vam za vaš odziv</string>
<string name="shared_string_world">Svet</string>
</resources>

View file

@ -157,8 +157,8 @@
<string name="poi_charity">Благодійний магазин</string>
<string name="poi_medical_supply">Медичне постачання</string>
<string name="poi_photo">Фотомагазин</string>
<string name="poi_traffic_calming_bump">Лежачий поліцейський</string>
<string name="poi_traffic_calming_hump">Штучне підвищення</string>
<string name="poi_traffic_calming_bump">Штучна дорожня нерівність</string>
<string name="poi_traffic_calming_hump">\"Лежачий поліцейський\"</string>
<string name="poi_traffic_calming_chicane">Шикана</string>
<string name="poi_leather">Магазин шкіри, галантарея</string>
<string name="poi_music">Музичний магазин</string>
@ -173,9 +173,9 @@
<string name="poi_pyrotechnics">Піротехніка</string>
<string name="poi_weapons">Магазин зброї</string>
<string name="poi_traffic_calming_cushion">Декілька лежачих поліцейських</string>
<string name="poi_traffic_calming_cushion">\"Берлінська подушка\"</string>
<string name="poi_traffic_calming_rumble_strip">Шумові полоси</string>
<string name="poi_traffic_calming_table">Довгий лежачий поліцейський</string>
<string name="poi_traffic_calming_table">Підвищений пішохідний перехід</string>
<string name="poi_traffic_calming_choker">Звуження дороги</string>
<string name="poi_traffic_signals">Світлофор</string>
@ -264,7 +264,7 @@
<string name="poi_rest_area">Зона відпочинку</string>
<string name="poi_water_well">Криниця</string>
<string name="poi_standpipe">Напірна труба</string>
<string name="poi_standpipe">Водорозбірна колонка</string>
<string name="poi_highway_crossing">Пішохідний перехід</string>
<string name="poi_energy">Енергетичний магазин</string>
@ -1269,7 +1269,7 @@
<string name="poi_email">Електронна пошта</string>
<string name="poi_fax">Факс</string>
<string name="facebook">Фейсбук</string>
<string name="twitter">Твіттер</string>
<string name="twitter">Twitter</string>
<string name="poi_skype">Скайп</string>
<string name="poi_youtube">Ютюб</string>
<string name="poi_instagram">Інстаграм</string>
@ -1761,7 +1761,7 @@
<string name="poi_summit_cross">Хрест на вершині: є</string>
<string name="poi_medical_system_mongolian_yes">Традиційна монгольська</string>
<string name="poi_payment_coins_0.5">Монети по 0,5$</string>
<string name="poi_payment_coins_0.5">Монети по $0,5</string>
<string name="poi_prison_camp">Колишній тюремний табір</string>
<string name="poi_medical_system_tibetan_yes">Традиційна тибетська</string>
<string name="poi_payment_coins_50c12">Монети по 50c, 1€ й 2€</string>
@ -1878,7 +1878,7 @@
<string name="poi_payment_uta_no">Картки UTA не приймаються</string>
<string name="poi_health_specialty_surgery_yes">Загальна хірургія</string>
<string name="poi_fire_hydrant_type_pond">Ставок</string>
<string name="poi_payment_efectivo_yes">Efectivo</string>
<string name="poi_payment_efectivo_yes">Готівка</string>
<string name="poi_health_specialty_radiology_yes">Радіологія</string>
<string name="poi_fire_hydrant_type_wall">Пожежний кран</string>
@ -2150,7 +2150,7 @@
<string name="poi_crossing_barrier_half">Бар\'єр на переїзді: половинний</string>
<string name="poi_payment_ep_avant_yes">AvantCard</string>
<string name="poi_architecture_constructivism">Архітектурний стиль: конструктивізм</string>
<string name="poi_historic_civilization_nuragic">Цивілізація: нурагічна (18 ст. до н.е. - 2 ст. н.е.)</string>
<string name="poi_historic_civilization_nuragic">Цивілізація: нурагічна (18 ст. до н.е. 2 ст. н.е.)</string>
<string name="poi_crossing_barrier_double_half">Бар\'єр на переїзді: подвійний половинний</string>
<string name="poi_architecture_umgebinde">Архітектурний стиль: umgebinde</string>
<string name="poi_historic_civilization_etruscan">Цивілізація: етруски (XII - VI ст. до н.е.)</string>
@ -3191,7 +3191,7 @@
<string name="poi_motorcycle_repair">Ремонт мотоциклів</string>
<string name="poi_resource_mercury">Ртуть</string>
<string name="poi_route_trolleybus_ref">Тролейбус</string>
<string name="poi_crop_poultry">Вирощується культура: кормова рослина</string>
<string name="poi_crop_poultry">Вирощується культура: свійська птиця</string>
<string name="poi_health_specialty_depth_psychology_yes">Глибинна психологія</string>
<string name="poi_nuclear_explosion_purpose_industrial_application_seismic_sounding">Мета вибуху: промислове застосування, сейсмічне зондування</string>
<string name="poi_treat_inpatient_no">Обслуговування в стаціонарі: ні</string>
@ -3861,7 +3861,11 @@
<string name="poi_hazard_minefield">Мінне поле</string>
<string name="poi_car_pooling">Місце об\'єднання автомобілів</string>
<string name="poi_car_pooling">Точка кар-шерінгу</string>
<string name="poi_ruins">Руїни</string>
<string name="poi_license_classes">Ліцензійні класи</string>
<string name="poi_hill">Пагорб</string>
</resources>

View file

@ -2,7 +2,7 @@
<resources>
<string name="asap">Швидко</string>
<string name="route_roundabout">Круговий рух : Візьміть %1$d з’їзд та продовжуйте рух</string>
<string name="route_roundabout">Круговий рух : Прямуйте до %1$d з’їзду та продовжуйте рух</string>
<string name="route_kl">Тримайтесь ліворуч</string>
<string name="route_kr">Тримайтесь праворуч</string>
<string name="rendering_attr_noPolygons_description">Відображати тільки контури, без заливки.</string>
@ -1824,7 +1824,7 @@
<string name="confirm_usage_speed_cameras">У багатьох країнах (Німеччина, Франція, Італія та інші) використання детекторів камер контролю швидкості не дозволено законом. OsmAnd не несе ніякої відповідальності, якщо Ви порушите закон. Будь ласка, натисніть кнопку „Так“, тільки якщо ви маєте право використовувати цю функцію.</string>
<string name="welmode_download_maps">Звантаження мап</string>
<string name="welcome_select_region">Щоб правильно показувати дорожні знаки та правила дорожнього руху, будь ласка, виберіть ваш регіон:</string>
<string name="welcome_text">OsmAnd забезпечує повністю автономний (оффлайн) перегляд мап і навігацію!</string>
<string name="welcome_text">OsmAnd забезпечує перегляд глобальної автономної (офлайн-) мапи і автономну навігацію.</string>
<string name="welcome_header">Ласкаво просимо</string>
<string name="current_route">Поточний маршрут</string>
<string name="osm_changes_added_to_local_edits">Зміни OSM додані до локального набору змін</string>
@ -2221,7 +2221,7 @@
<string name="download_files_error_not_enough_space">Недостатньо пам\'яті!
Необхідно {3} МБ тимчасової та {1} МБ постійної пам\'яті.
На разі доступно лише {2} МБ.</string>
<string name="download_files_question_space_with_temp">Звантажити {0} файл(їв)? Використовується {3} МБ тимчасової та {1} МБ постійної пам’яті (наразі вільно лише {2} МБ).</string>
<string name="download_files_question_space_with_temp">Звантажити {0} файл(ів)\? Використовується {3} Мб тимчасової та {1} Мб постійної пам’яті (наразі вільно лише {2} Мб)</string>
<string name="donations">Пожертвування</string>
<string name="osm_live_subscribe_btn">Підписатися</string>
<string name="osm_live_hide_user_name">Не показувати моє ім\'я у звітах</string>
@ -2518,7 +2518,7 @@
<string name="quick_action_duplicate">Виявлено дублікат імені</string>
<string name="quick_action_showhide_poi_descr">Натискання на цю кнопку показує або приховує POI на мапі.</string>
<string name="quick_action_gpx_category_descr">Виберіть категорію (опціонально).</string>
<string name="quick_action_page_list_descr">Натискання на цю кнопку циклічно перемикає елементи списку нижче.</string>
<string name="quick_action_page_list_descr">Натискання на цю кнопку циклічно гортає елементи списку нижче.</string>
<string name="quick_action_map_overlay">Змінити мапу покриття</string>
<string name="quick_action_map_overlay_title">Мапи покриття</string>
<string name="quick_action_map_overlay_action">Додати мапу покриття</string>
@ -3180,14 +3180,19 @@
\nНадішліть нам відгук</string>
<string name="commiting_way">Створюється шлях…</string>
<string name="test_voice_desrc">Натисніть кнопку та прослуховуйте відповідну голосову підказку, щоб визначити відсутні або хибні підказки.</string>
<string name="release_3_2_pre">• Виправлено аварійне завершення програми при запуску з нелатинськими мапами
<string name="release_3_2_pre">• Виправлено аварійне завершення програми при запуску, що траплялося на деяких пристроях
\n
\n• Нова можливість Позначок: відображати пройдені позначки
\n
\n• Історія пошуку тепер показує категорії, які ви раніше шукали
\n
\n• Виправлено аварійне завершення програми при запуску з нелатинськими мапами
\n
\n• Підвищено швидкість промальовки на пристроях з Android 8.0
\n
\n• Підтримка редагування полігональних (не-amenity) об\'єктів
\n
\n• Вимірювання відстані: додано кнопку «Виміряти» до Дій у контекстному меню
\n
\n</string>
<string name="ask_for_location_permission">Будь ласка, надайте OsmAnd дозвіл визначати місцезнаходження для того, щоб продовжити.</string>
<string name="rendering_value_black_name">Чорний</string>
@ -3197,4 +3202,7 @@
<string name="keep_passed_markers_descr">Позначки, додані як група Закладок або маршрутних точок GPX і позначені пройденими, залишаться на мапі. Якщо група неактивна, позначки зникнуть з мапи.</string>
<string name="keep_passed_markers">Залишити пройдені позначки на мапі</string>
<string name="more_transport_on_stop_hint">На цій зупинці є інші транспортні засоби.</string>
<string name="markers_remove_dialog_msg">Видалити позначку мапи \'%s\'\?</string>
<string name="edit_map_marker">Редагувати позначку мапи</string>
<string name="third_party_application">Стороння програма</string>
</resources>

View file

@ -1041,7 +1041,7 @@
<string name="poi_supervised_yes">有監管</string>
<string name="poi_supervised_no">沒有監管</string>
<string name="poi_mill_pond">磨房水塘</string>
<string name="twitter">Twitter</string>
<string name="twitter">推特</string>
<string name="poi_skype">Skype</string>
<string name="poi_youtube">Youtube</string>
<string name="poi_instagram">Instagram</string>

View file

@ -1024,6 +1024,7 @@
<string name="poi_bank">Bank</string>
<string name="poi_amenity_atm">ATM</string>
<string name="poi_atm">ATM</string>
<string name="poi_payment_terminal">Payment terminal</string>
<string name="poi_money_lender">Money lender</string>
<string name="poi_pawnbroker">Pawnbroker</string>

View file

@ -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;

View file

@ -723,7 +723,7 @@ public class OsmandSettings {
public final CommonPreference<WikiArticleShowImages> WIKI_ARTICLE_SHOW_IMAGES = new EnumIntPreference<>("wikivoyage_show_imgs", WikiArticleShowImages.OFF, WikiArticleShowImages.values()).makeGlobal();
public final CommonPreference<Boolean> SELECT_MARKER_ON_SINGLE_TAP = new BooleanPreference("select_marker_on_single_tap", false).makeProfile();
public final CommonPreference<Boolean> KEEP_PASSED_MARKERS_ON_MAP = new BooleanPreference("keep_passed_markers_on_map", true).makeProfile();
public final CommonPreference<Boolean> KEEP_PASSED_MARKERS_ON_MAP = new BooleanPreference("keep_passed_markers_on_map", false).makeProfile();
public final CommonPreference<Boolean> COORDS_INPUT_USE_RIGHT_SIDE = new BooleanPreference("coords_input_use_right_side", true).makeGlobal();
public final OsmandPreference<Format> COORDS_INPUT_FORMAT = new EnumIntPreference<>("coords_input_format", Format.DD_MM_MMM, Format.values()).makeGlobal();

View file

@ -246,6 +246,21 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable<PoiUIFilter>
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;
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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<String> 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<String> 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()) {
@ -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<String, String> 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<String> getValues(@Nullable QStringStringHash set) {
List<String> 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<Object> set, @NonNull Amenity amenity) {
for (Object o : set) {
if (o instanceof Amenity && ((Amenity) o).compareTo(amenity) == 0) {
return false;
} else if (o instanceof TransportStop && ((TransportStop) o).getName().startsWith(amenity.getName())) {
return false;
}
}
return true;
}
public boolean disableSingleTap() {
boolean res = false;
for (OsmandMapLayer lt : view.getLayers()) {