diff --git a/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java b/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java index a6bcad107d..b58237dfe0 100644 --- a/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java +++ b/OsmAnd-java/src/main/java/net/osmand/data/TransportRoute.java @@ -43,7 +43,10 @@ public class TransportRoute extends MapObject { } public List getForwardWays() { - return forwardWays == null ? Collections.emptyList() : forwardWays; + if(forwardWays == null) { + return Collections.emptyList(); + } + return forwardWays; } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java index e980f3c870..a7c5c08d66 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java @@ -1,16 +1,9 @@ package net.osmand.router; -import net.osmand.Location; -import net.osmand.binary.BinaryMapIndexReader; -import net.osmand.binary.BinaryMapIndexReader.SearchRequest; -import net.osmand.data.LatLon; -import net.osmand.data.QuadRect; -import net.osmand.data.TransportRoute; -import net.osmand.data.TransportSchedule; -import net.osmand.data.TransportStop; -import net.osmand.osm.edit.Node; -import net.osmand.osm.edit.Way; -import net.osmand.util.MapUtils; +import gnu.trove.iterator.TIntIterator; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; import java.io.IOException; import java.util.ArrayList; @@ -21,10 +14,16 @@ import java.util.List; import java.util.Map; import java.util.PriorityQueue; -import gnu.trove.iterator.TIntIterator; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.map.hash.TIntObjectHashMap; -import gnu.trove.map.hash.TLongObjectHashMap; +import net.osmand.binary.BinaryMapIndexReader; +import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.data.LatLon; +import net.osmand.data.QuadRect; +import net.osmand.data.TransportRoute; +import net.osmand.data.TransportSchedule; +import net.osmand.data.TransportStop; +import net.osmand.osm.edit.Node; +import net.osmand.osm.edit.Way; +import net.osmand.util.MapUtils; public class TransportRoutePlanner { @@ -39,6 +38,9 @@ public class TransportRoutePlanner { for(TransportRouteSegment s : endStops) { endSegments.put(s.getId(), s); } + if(startStops.size() == 0) { + return Collections.emptyList(); + } PriorityQueue queue = new PriorityQueue(startStops.size(), new SegmentsComparator(ctx)); for(TransportRouteSegment r : startStops){ r.walkDist = (float) MapUtils.getDistance(r.getLocation(), start); @@ -96,11 +98,12 @@ public class TransportRoutePlanner { } else { travelTime += ctx.cfg.stopTime + segmentDist / ctx.cfg.travelSpeed; } - if(travelDist > finishTime + ctx.cfg.finishTimeSeconds) { + if(segment.distFromStart + travelTime > finishTime + ctx.cfg.finishTimeSeconds) { break; } sgms.clear(); sgms = ctx.getTransportStops(stop.x31, stop.y31, true, sgms); + ctx.visitedStops++; for (TransportRouteSegment sgm : sgms) { if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) { return null; @@ -108,31 +111,31 @@ public class TransportRoutePlanner { if (segment.wasVisited(sgm)) { continue; } - TransportRouteSegment rrs = new TransportRouteSegment(sgm); - rrs.parentRoute = segment; - rrs.parentStop = ind; - rrs.walkDist = MapUtils.getDistance(rrs.getLocation(), stop.getLocation()); - rrs.parentTravelTime = travelTime; - rrs.parentTravelDist = travelDist; - double walkTime = rrs.walkDist / ctx.cfg.walkSpeed + TransportRouteSegment nextSegment = new TransportRouteSegment(sgm); + nextSegment.parentRoute = segment; + nextSegment.parentStop = ind; + nextSegment.walkDist = MapUtils.getDistance(nextSegment.getLocation(), stop.getLocation()); + nextSegment.parentTravelTime = travelTime; + nextSegment.parentTravelDist = travelDist; + double walkTime = nextSegment.walkDist / ctx.cfg.walkSpeed + (ctx.cfg.getChangeTime()); - rrs.distFromStart = segment.distFromStart + travelTime + walkTime; + nextSegment.distFromStart = segment.distFromStart + travelTime + walkTime; if(ctx.cfg.useSchedule) { int tm = (sgm.departureTime - ctx.cfg.scheduleTimeOfDay) * 10; - if(tm >= rrs.distFromStart) { - rrs.distFromStart = tm; - queue.add(rrs); + if(tm >= nextSegment.distFromStart) { + nextSegment.distFromStart = tm; + queue.add(nextSegment); } } else { - queue.add(rrs); + queue.add(nextSegment); } } - TransportRouteSegment f = endSegments.get(segmentId); + TransportRouteSegment finalSegment = endSegments.get(segmentId); double distToEnd = MapUtils.getDistance(stop.getLocation(), end); - if (f != null && distToEnd < ctx.cfg.walkRadius) { + if (finalSegment != null && distToEnd < ctx.cfg.walkRadius) { if (finish == null || minDist > distToEnd) { minDist = distToEnd; - finish = new TransportRouteSegment(f); + finish = new TransportRouteSegment(finalSegment); finish.parentRoute = segment; finish.parentStop = ind; finish.walkDist = distToEnd; @@ -198,9 +201,11 @@ public class TransportRoutePlanner { private List prepareResults(TransportRoutingContext ctx, List results) { Collections.sort(results, new SegmentsComparator(ctx)); List lst = new ArrayList(); - System.out.println(String.format("Calculated %.1f seconds, found %d results, visited %d routes, loaded %d tiles (%d ms read, %d ms total),", - (System.currentTimeMillis() - ctx.startCalcTime) / 1000.0, results.size(), ctx.visitedRoutesCount, - ctx.quadTree.size(), ctx.readTime / (1000 * 1000), ctx.loadTime / (1000 * 1000))); + System.out.println(String.format("Calculated %.1f seconds, found %d results, visited %d routes / %d stops, loaded %d tiles (%d ms read, %d ms total), loaded ways %d (%d wrong)", + (System.currentTimeMillis() - ctx.startCalcTime) / 1000.0, results.size(), + ctx.visitedRoutesCount, ctx.visitedStops, + ctx.quadTree.size(), ctx.readTime / (1000 * 1000), ctx.loadTime / (1000 * 1000), + ctx.loadedWays, ctx.wrongLoadedWays)); for(TransportRouteSegment res : results) { if (ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) { return null; @@ -214,9 +219,15 @@ public class TransportRoutePlanner { return null; } if (p.parentRoute != null) { - TransportRouteResultSegment sg = new TransportRouteResultSegment(p.parentRoute.road, - p.parentRoute.segStart, p.parentStop, p.parentRoute.walkDist, - p.departureTime); + TransportRouteResultSegment sg = new TransportRouteResultSegment(); + sg.route = p.parentRoute.road; + sg.start = p.parentRoute.segStart; + sg.end = p.parentStop; + sg.walkDist = p.parentRoute.walkDist; + sg.walkTime = sg.walkDist / ctx.cfg.walkSpeed; + sg.depTime = p.departureTime; + sg.travelInaccurateDist = p.parentTravelDist; + sg.travelTime = p.parentTravelTime; route.segments.add(0, sg); } p = p.parentRoute; @@ -278,20 +289,19 @@ public class TransportRoutePlanner { public static class TransportRouteResultSegment { + private static final boolean DISPLAY_FULL_SEGMENT_ROUTE = false; private static final int DISPLAY_SEGMENT_IND = 0; - public final TransportRoute route; - public final int start; - public final int end; - public final double walkDist ; - public final int depTime; + public TransportRoute route; + public double walkTime; + public double travelInaccurateDist; + public double travelTime; + public int start; + public int end; + public double walkDist ; + public int depTime; - public TransportRouteResultSegment(TransportRoute route, int start, int end, double walkDist, int depTime) { - this.route = route; - this.start = start; - this.end = end; - this.walkDist = walkDist; - this.depTime = depTime; + public TransportRouteResultSegment() { } public int getArrivalTime() { @@ -534,9 +544,9 @@ public class TransportRoutePlanner { private static final int SHIFT_DEPTIME = 14; // assume less than 1024 stops TransportRouteSegment parentRoute = null; - int parentStop; - double parentTravelTime; // travel time - double parentTravelDist; // inaccurate + int parentStop; // last stop to exit for parent route + double parentTravelTime; // travel time for parent route + double parentTravelDist; // travel distance for parent route (inaccurate) // walk distance to start route location (or finish in case last segment) double walkDist = 0; @@ -643,6 +653,7 @@ public class TransportRoutePlanner { // stats public long startCalcTime; public int visitedRoutesCount; + public int visitedStops; public int wrongLoadedWays; public int loadedWays; public long loadTime; diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java index d2bf29d650..a046021ee2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java @@ -4,7 +4,7 @@ public class TransportRoutingConfiguration { public static final String KEY = "public_transport"; - public int ZOOM_TO_LOAD_TILES = 14; + public int ZOOM_TO_LOAD_TILES = 15; public int walkRadius = 1500; // ? 3000 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 f6379410fa..ac8e57c4a2 100644 --- a/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java +++ b/OsmAnd-java/src/main/java/net/osmand/search/SearchUICore.java @@ -858,8 +858,8 @@ public class SearchUICore { return cmp; } } - int st1 = Algorithms.extractFirstIntegerNumber(o1.localeName); - int st2 = Algorithms.extractFirstIntegerNumber(o2.localeName); + int st1 = o1.localeName == null ? -10000 : Algorithms.extractFirstIntegerNumber(o1.localeName); + int st2 = o2.localeName == null ? -10000 : Algorithms.extractFirstIntegerNumber(o2.localeName); if (st1 != st2) { return Algorithms.compare(st1, st2); } diff --git a/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java b/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java index f033992a46..2368fef570 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/MapUtils.java @@ -112,6 +112,7 @@ public class MapUtils { } + /** * Gets distance in meters */ diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 5901860687..9d5eb59fed 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -66,6 +66,16 @@ android { warningsAsErrors false } + bundle { + language { + // Specifies that the app bundle should not support + // configuration APKs for language resources. These + // resources are instead packaged with each base and + // dynamic feature APK. + enableSplit = false + } + } + // related to kuromoji //packagingOptions { // exclude '/META-INF/CONTRIBUTORS.md' diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 88d3e14aca..0839d4d7c8 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -10,7 +10,9 @@ - For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience Thx - Hardy ---> %s mode + %s mode + Value of tag \"%s\" cannot exceed 255 chars. \nPlease edit it before continue. + Length of \"%s\" value Learn more about how OsmAnd calculates routes in our blog. Public transport routes are now in the beta testing phase, so errors and inaccuracies may occur. Add intermediate point diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java index 8749143d36..5f46d5d387 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPoiDialogFragment.java @@ -3,6 +3,7 @@ package net.osmand.plus.osmedit; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; @@ -108,7 +109,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { private View view; @Override - public void onAttach(Activity activity) { + public void onAttach(Context activity) { super.onAttach(activity); OsmEditingPlugin plugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class); if (getSettings().OFFLINE_EDITION.get() @@ -400,7 +401,14 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { } private void trySave() { - if (TextUtils.isEmpty(poiTypeEditText.getText())) { + String tagWithExceedingValue = isTextLengthInRange(); + if (!Algorithms.isEmpty(tagWithExceedingValue)){ + ValueExceedLimitDialogFragment f = new ValueExceedLimitDialogFragment(); + Bundle args = new Bundle(); + args.putString("tag", tagWithExceedingValue); + f.setArguments(args); + f.show(getChildFragmentManager(), "exceedDialog"); + } else if (TextUtils.isEmpty(poiTypeEditText.getText())) { HashSet tagsCopy = new HashSet<>(); tagsCopy.addAll(editPoiData.getTagValues().keySet()); if (Algorithms.isEmpty(editPoiData.getTag(OSMSettings.OSMTagKey.ADDR_HOUSE_NUMBER.getValue()))) { @@ -422,12 +430,22 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { } else if (editPoiData.getPoiCategory() == getMyApplication().getPoiTypes().getOtherPoiCategory()) { poiTypeEditText.setError(getResources().getString(R.string.please_specify_poi_type)); } else if (editPoiData.getPoiTypeDefined() == null) { - poiTypeEditText.setError(getResources().getString(R.string.please_specify_poi_type_only_from_list)); + poiTypeEditText.setError( + getResources().getString(R.string.please_specify_poi_type_only_from_list)); } else { save(); } } + private String isTextLengthInRange() { + for (String s: editPoiData.getChangedTags()) { + if (editPoiData.getTag(s).length() > 255) { + return s; + } + } + return ""; + } + private boolean testTooManyCapitalLetters(String name) { if(name == null) { return false; @@ -889,6 +907,23 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment { } } + public static class ValueExceedLimitDialogFragment extends DialogFragment { + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + String msg = getString(R.string.save_poi_value_exceed_length); + String fieldTag = getArguments().getString("tag", ""); + if(!Algorithms.isEmpty(fieldTag)) { + msg = String.format(msg, fieldTag); + } + builder.setTitle(String.format(getResources().getString(R.string.save_poi_value_exceed_length_title), fieldTag)) + .setMessage(msg) + .setNegativeButton(R.string.shared_string_ok, null); + return builder.create(); + } + } + private TextView.OnEditorActionListener mOnEditorActionListener = new TextView.OnEditorActionListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index a8a4a5cba8..8d45cc98f6 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -714,19 +714,15 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { - //MapActivity mapActivity = getMapActivity(); - //if (mapActivity != null) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { if (selected.size() > 0) { - // OsmandApplication app = mapActivity.getMyApplication(); ApplicationMode next = selected.iterator().next(); - // if (app.getRoutingHelper().isRouteCalculated()) { - // app.getSettings().LAST_ROUTE_APPLICATION_MODE.set(next); - // } updateApplicationMode(am, next); } updateFinishPointView(); updateOptionsButtons(); - //} + } } }; final List values = new ArrayList(ApplicationMode.values(mapActivity.getMyApplication())); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java index 308553fdae..32e191fe16 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/WarningCard.java @@ -23,7 +23,7 @@ import net.osmand.plus.wikipedia.WikipediaDialogFragment; public class WarningCard extends BaseCard { - public static final String OSMAND_BLOG_LINK = "https://osmand.net/blog"; + public static final String OSMAND_BLOG_LINK = "https://osmand.net/blog/guideline-pt"; public WarningCard(MapActivity mapActivity) { super(mapActivity); diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 5d1c8cfcaf..828e50356e 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -943,7 +943,6 @@ public class RoutingHelper { public void recalculateRouteDueToSettingsChange() { clearCurrentRoute(finalLocation, intermediatePoints); - getSettings().LAST_ROUTE_APPLICATION_MODE.set(getAppMode()); if (isPublicTransportMode()) { Location start = lastFixedLocation; LatLon finish = finalLocation; diff --git a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java index e097f40451..2126cf960d 100644 --- a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java @@ -158,6 +158,7 @@ public class TransportRoutingHelper { private void startRouteCalculationThread(TransportRouteCalculationParams params) { synchronized (this) { final Thread prevRunningJob = currentRunningJob; + app.getSettings().LAST_ROUTE_APPLICATION_MODE.set(routingHelper.getAppMode()); RouteRecalculationThread newThread = new RouteRecalculationThread("Calculating public transport route", params); currentRunningJob = newThread;