Ejemplo n.º 1
0
        bool UpdateFromProvider(CachedDistance distance)
        {
            if (ErrorWays.Any(x => x.FromHash == distance.FromGeoHash && x.ToHash == distance.ToGeoHash))
            {
                //logger.Warn("Повторный запрос дистанции с ошибкой расчета. Пропускаем...");
                return(false);
            }

            //logger.Info("Запрашиваем путь {0}->{1} у сервиса {0}.", distance.FromGeoHash, distance.ToGeoHash, Provider);
            List <PointOnEarth> points = new List <PointOnEarth>();
            double latitude, longitude;

            CachedDistance.GetLatLon(distance.FromGeoHash, out latitude, out longitude);
            points.Add(new PointOnEarth(latitude, longitude));
            CachedDistance.GetLatLon(distance.ToGeoHash, out latitude, out longitude);
            points.Add(new PointOnEarth(latitude, longitude));
            bool ok = false;

            if (Provider == DistanceProvider.Osrm)
            {
                var result = OsrmMain.GetRoute(points, false, GeometryOverview.Full);
                ok = result?.Code == "Ok";
                if (ok && result.Routes.Any())
                {
                    distance.DistanceMeters   = result.Routes.First().TotalDistance;
                    distance.TravelTimeSec    = result.Routes.First().TotalTimeSeconds;
                    distance.PolylineGeometry = result.Routes.First().RouteGeometry;
                }
            }
            else
            {
                var result = SputnikMain.GetRoute(points, false, true);
                ok = result.Status == 0;
                if (ok)
                {
                    distance.DistanceMeters   = result.RouteSummary.TotalDistance;
                    distance.TravelTimeSec    = result.RouteSummary.TotalTimeSeconds;
                    distance.PolylineGeometry = result.RouteGeometry;
                }
            }

            if (ok)
            {
                lock (uow) {
                    AddNewCacheDistance(distance);
                    uow.TrySave(distance);
                    uow.Commit();
                }
                addedCached++;
                return(true);
            }

            ErrorWays.Add(new WayHash(distance.FromGeoHash, distance.ToGeoHash));
            totalErrors++;
            return(false);
        }
Ejemplo n.º 2
0
        public virtual SputnikRouteResponse CalculateDistanceToBase()
        {
            var lastAddress = RouteList.Addresses
                              .Where(x => x.Status == RouteListItemStatus.Completed)
                              .OrderByDescending(x => x.StatusLastUpdate)
                              .FirstOrDefault();

            if (lastAddress == null)
            {
                DistanceToBase = null;
                return(null);
            }

            var points    = new List <PointOnEarth>();
            var lastPoint = lastAddress.Order.DeliveryPoint;

            points.Add(new PointOnEarth(lastPoint.Latitude.Value, lastPoint.Longitude.Value));
            //Координаты базы
            if (lastPoint.District == null)
            {
                logger.Warn("Для точки доставки не удалось подобрать часть города. Расчёт расстояния до центра СПб");
                points.Add(new PointOnEarth(Constants.CenterOfCityLatitude, Constants.CenterOfCityLongitude));
            }
            else if (lastPoint.District != null && lastPoint.District.GeographicGroup.BaseCoordinatesExist)
            {
                var gg = lastPoint.District.GeographicGroup;
                points.Add(new PointOnEarth((double)gg.BaseLatitude.Value, (double)gg.BaseLongitude.Value));
            }
            else
            {
                logger.Error("В подобранной части города не указаны координаты базы");
                return(null);
            }
            var response = SputnikMain.GetRoute(points, false, true);

            if (response.Status == 0)
            {
                DistanceToBase = (double)response.RouteSummary.TotalDistanceKm;
            }
            else
            {
                logger.Error("Ошибка при получении расстояния до базы {0}: {1}", response.Status, response.StatusMessage);
            }
            return(response);
        }
Ejemplo n.º 3
0
        private CachedDistance LoadDistanceFromService(long fromHash, long toHash)
        {
            CachedDistance cachedValue = null;
            bool           ok          = false;

            if (fromHash == toHash)
            {
                cachedValue = new CachedDistance {
                    DistanceMeters = 0,
                    TravelTimeSec  = 0,
                    FromGeoHash    = fromHash,
                    ToGeoHash      = toHash
                };
                AddNewCacheDistance(cachedValue);
                addedCached++;
                ok = true;
            }

            if (!ok)
            {
                List <PointOnEarth> points = new List <PointOnEarth> {
                    CachedDistance.GetPointOnEarth(fromHash),
                    CachedDistance.GetPointOnEarth(toHash)
                };
                if (Provider == DistanceProvider.Osrm)
                {
                    var result = OsrmMain.GetRoute(points, false, GeometryOverview.False);
                    ok = result?.Code == "Ok";
                    if (ok && result.Routes.Any())
                    {
                        cachedValue = new CachedDistance {
                            DistanceMeters = result.Routes.First().TotalDistance,
                            TravelTimeSec  = result.Routes.First().TotalTimeSeconds,
                            FromGeoHash    = fromHash,
                            ToGeoHash      = toHash
                        };
                    }
                }
                else
                {
                    var result = SputnikMain.GetRoute(points, false, false);
                    ok = result.Status == 0;
                    if (ok)
                    {
                        cachedValue = new CachedDistance {
                            DistanceMeters = result.RouteSummary.TotalDistance,
                            TravelTimeSec  = result.RouteSummary.TotalTimeSeconds,
                            FromGeoHash    = fromHash,
                            ToGeoHash      = toHash
                        };
                    }
                }
            }
            if (MultiTaskLoad && ok)
            {
                lock (UoW) {
                    UoW.TrySave(cachedValue as CachedDistance, false);
                    unsavedItems++;
                    if (unsavedItems >= SaveBy)
                    {
                        FlushCache();
                    }
                    AddNewCacheDistance(cachedValue);
                    addedCached++;
                }
                return(cachedValue);
            }
            if (ok)
            {
                AddNewCacheDistance(cachedValue);
                addedCached++;
                return(cachedValue);
            }

            ErrorWays.Add(new WayHash(fromHash, toHash));
            totalErrors++;
            //FIXME Реализовать запрос манхентанского расстояния.
            return(null);
        }
Ejemplo n.º 4
0
        protected void OnButtonFindGapClicked(object sender, EventArgs e)
        {
            trackOnGapOverlay.Clear();
            tracksDistance.RemoveAll(x => x.Id == "MissingTrack");
            string message          = "Найдены разрывы в треке:";
            double replacedDistance = 0;

            TrackPoint lastPoint = null;

            foreach (var point in track.TrackPoints)
            {
                if (lastPoint == null)
                {
                    lastPoint = point;
                    continue;
                }

                var distance = GMapProviders.EmptyProvider.Projection.GetDistance(
                    new PointLatLng(lastPoint.Latitude, lastPoint.Longitude),
                    new PointLatLng(point.Latitude, point.Longitude));

                if (distance > 0.5)
                {
                    logger.Info("Найден разрыв в треке расстоянием в {0}", distance);
                    message += string.Format("\n* разрыв c {1:t} по {2:t} — {0:N1} км.",
                                             distance,
                                             lastPoint.TimeStamp,
                                             point.TimeStamp
                                             );
                    replacedDistance += distance;

                    var addressesByCompletion = routeList.Addresses
                                                .Where(x => x.Status == RouteListItemStatus.Completed)
                                                .OrderBy(x => x.StatusLastUpdate)
                                                .ToList();

                    RouteListItem addressBeforeGap = addressesByCompletion.LastOrDefault(x => x.StatusLastUpdate < lastPoint.TimeStamp.AddMinutes(2));
                    RouteListItem addressAfterGap  = addressesByCompletion.FirstOrDefault(x => x.StatusLastUpdate > point.TimeStamp.AddMinutes(-2));

                    var beforeIndex = addressBeforeGap == null ? -1 : addressesByCompletion.IndexOf(addressBeforeGap);
                    var afterIndex  = addressAfterGap == null ? addressesByCompletion.Count : addressesByCompletion.IndexOf(addressAfterGap);
                    var routePoints = new List <PointOnEarth> {
                        new PointOnEarth(lastPoint.Latitude, lastPoint.Longitude)
                    };

                    if (afterIndex - beforeIndex > 1)
                    {
                        var throughAddress = addressesByCompletion.GetRange(beforeIndex + 1, afterIndex - beforeIndex - 1);
                        logger.Info("В разрыве найдены выполенные адреса порядковый(е) номер(а) {0}", String.Join(", ", throughAddress.Select(x => x.IndexInRoute)));
                        routePoints.AddRange(
                            throughAddress.Where(x => x.Order?.DeliveryPoint?.Latitude != null && x.Order?.DeliveryPoint?.Longitude != null)
                            .Select(x => new PointOnEarth(x.Order.DeliveryPoint.Latitude.Value, x.Order.DeliveryPoint.Longitude.Value)));

                        message += $" c выполненными адресами({beforeIndex + 2}-{afterIndex}) п/п в МЛ " + String.Join(", ", throughAddress.Select(x => x.IndexInRoute));
                    }
                    routePoints.Add(new PointOnEarth(point.Latitude, point.Longitude));

                    var missedTrack = SputnikMain.GetRoute(routePoints, false, true);
                    if (missedTrack == null)
                    {
                        MessageDialogHelper.RunErrorDialog("Не удалось получить ответ от сервиса \"Спутник\"");
                        return;
                    }
                    if (missedTrack.Status != 0)
                    {
                        MessageDialogHelper.RunErrorDialog("Cервис \"Спутник\" сообщил об ошибке {0}: {1}", missedTrack.Status, missedTrack.StatusMessageRus);
                        return;
                    }

                    var decodedPoints = Polyline.DecodePolyline(missedTrack.RouteGeometry);
                    var points        = decodedPoints.Select(p => new PointLatLng(p.Latitude * 0.1, p.Longitude * 0.1)).ToList();

                    var route = new GMapRoute(points, "MissedRoute")
                    {
                        Stroke = new Pen(Color.DarkMagenta)
                        {
                            Width     = 4,
                            DashStyle = System.Drawing.Drawing2D.DashStyle.Dot
                        }
                    };

                    trackOnGapOverlay.Routes.Add(route);
                }

                lastPoint = point;
            }

            if (trackOnGapOverlay.Routes.Count > 0)
            {
                var distanceLayout = MakeDistanceLayout(trackOnGapOverlay.Routes.ToArray());
                distanceLayout.Id = "MissingTrack";
                tracksDistance.Add(distanceLayout);
                var oldDistance         = track.DistanceEdited ? trackRoute.Distance : track.Distance;
                var missedRouteDistance = trackOnGapOverlay.Routes.Sum(x => x.Distance);
                var newDistance         = oldDistance - replacedDistance + missedRouteDistance;
                var diffDistance        = newDistance - oldDistance;

                message += $"\n Старая длинна трека:{oldDistance:N1} км." +
                           $"\n Новая длинна трека: {newDistance:N1} км.(+{diffDistance:N1})" +
                           "\n Сохранить изменения длинны трека?";

                if (MessageDialogHelper.RunQuestionDialog(message))
                {
                    track.Distance       = newDistance;
                    track.DistanceEdited = true;
                    UoW.Save(track);
                    UoW.Commit();
                    UpdateDistanceLabel();
                }
            }
            else
            {
                MessageDialogHelper.RunInfoDialog("Разрывов в треке не найдено.");
            }
        }