Esempio n. 1
0
        public override async Task <PlayerUpdateResponse> Walk(GeoCoordinate targetLocation, Func <Task <bool> > functionExecutedWhileWalking, ISession session, CancellationToken cancellationToken, double walkSpeed = 0.0)
        {
            GetGoogleInstance(session);

            _minStepLengthInMeters = session.LogicSettings.DefaultStepLength;
            var currentLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude, _client.CurrentAltitude);
            var googleResult    = _googleDirectionsService.GetDirections(currentLocation, new List <GeoCoordinate>(), targetLocation);

            if (googleResult.Directions.status.Equals("OVER_QUERY_LIMIT"))
            {
                return(await RedirectToNextFallbackStrategy(session.LogicSettings, targetLocation, functionExecutedWhileWalking, session, cancellationToken));
            }

            var googleWalk = GoogleWalk.Get(googleResult);

            session.EventDispatcher.Send(new FortTargetEvent {
                Name = FortInfo.Name, Distance = googleResult.GetDistance(), Route = "GoogleWalk"
            });
            List <GeoCoordinate> points = googleWalk.Waypoints;

            return(await DoWalk(points, session, functionExecutedWhileWalking, currentLocation, targetLocation, cancellationToken));
        }
        public async Task <GoogleWalk> GetDirections(GeoCoordinate origin, List <GeoCoordinate> waypoints, GeoCoordinate destino)
        {
            GoogleResult googleResult = null;

            try
            {
                if (_cache)
                {
                    var item = OldResults
                               .FirstOrDefault(pesquisa => IsSameAdress(origin, waypoints, destino, pesquisa));
                    if (item != null)
                    {
                        item.FromCache = true;
                        googleResult   = item;
                    }
                }

                if (googleResult == null)
                {
                    var url = GetUrl(origin, waypoints, destino);

                    using (var client = new HttpClient())
                    {
                        client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/");
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                        HttpResponseMessage responseMessage = await client.GetAsync(url).ConfigureAwait(false);

                        var resposta = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);

                        var google = JsonConvert.DeserializeObject <DirectionsResponse>(resposta);
                        if (google.status.Equals("OVER_QUERY_LIMIT"))
                        {
                            // If we get an error, don't cache empty GoogleResult.  Just return null.
                            return(null);
                        }

                        var resultadoPesquisa = new GoogleResult
                        {
                            Directions  = google,
                            RequestDate = DateTime.Now,
                            Origin      = origin,
                            Waypoints   = waypoints,
                            Destiny     = destino,
                            FromCache   = false,
                        };

                        if (_cache)
                        {
                            SaveResult(resultadoPesquisa);
                        }

                        googleResult = resultadoPesquisa;
                    }
                }

                if (googleResult != null)
                {
                    return(GoogleWalk.Get(googleResult));
                }
            }
            catch (ActiveSwitchByRuleException ex)
            {
                throw ex;
            }
            catch (Exception)
            {
            }
            return(null);
        }
Esempio n. 3
0
        public async Task <PlayerUpdateResponse> Walk(GeoCoordinate targetLocation, Func <Task <bool> > functionExecutedWhileWalking, ISession session, CancellationToken cancellationToken)
        {
            GetGoogleInstance(session);

            _minStepLengthInMeters = session.LogicSettings.DefaultStepLength;
            var currentLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude, _client.CurrentAltitude);
            var googleResult    = _googleDirectionsService.GetDirections(currentLocation, new List <GeoCoordinate>(), targetLocation);

            if (googleResult.Directions.status.Equals("OVER_QUERY_LIMIT"))
            {
                return(await RedirectToHumanStrategy(targetLocation, functionExecutedWhileWalking, session, cancellationToken));
            }

            var googleWalk = GoogleWalk.Get(googleResult);

            PlayerUpdateResponse result = null;
            var points = googleWalk.Waypoints;

            //filter google defined waypoints and remove those that are too near to the previous ones
            var waypointsDists       = new Dictionary <Tuple <GeoCoordinate, GeoCoordinate>, double>();
            var minWaypointsDistance = RandomizeStepLength(_minStepLengthInMeters);

            Logger.Write($"Generating waypoints, will remove those with distance form previous less than: {minWaypointsDistance.ToString("0.000")}", LogLevel.Debug, force: true);
            for (var i = 0; i < points.Count; i++)
            {
                if (i > 0)
                {
                    var dist = LocationUtils.CalculateDistanceInMeters(points[i - 1], points[i]);
                    waypointsDists[new Tuple <GeoCoordinate, GeoCoordinate>(points[i - 1], points[i])] = dist;
                    Logger.Write($"WP{i-1}-{i}: {{{points[i-1].Latitude},{points[i-1].Longitude}}} -{{{points[i].Latitude},{points[i].Longitude}}}, dist: {dist.ToString("0.000")}", LogLevel.Debug, force: true);
                }
            }

            var tooNearPoints = waypointsDists.Where(kvp => kvp.Value < minWaypointsDistance).Select(kvp => kvp.Key.Item1).ToList();

            foreach (var tooNearPoint in tooNearPoints)
            {
                points.Remove(tooNearPoint);
            }
            if (points.Any()) //check if first waypoint is the current location (this is what google returns), in such case remove it!
            {
                var firstStep = points.First();
                if (firstStep == currentLocation)
                {
                    points.Remove(points.First());
                }
            }
            var stringifiedPath = string.Join(",\n", points.Select(point => $"{{lat: {point.Latitude}, lng: {point.Longitude}}}"));

            session.EventDispatcher.Send(new PathEvent
            {
                IsCalculated    = true,
                StringifiedPath = stringifiedPath
            });

            var walkedPointsList = new List <GeoCoordinate>();

            foreach (var nextStep in points)
            {
                Logger.Write($"Leading to a next google waypoint: {{lat: {nextStep.Latitude}, lng: {nextStep.Longitude}}}", LogLevel.Debug, force: true);
                currentLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude);
                if (_currentWalkingSpeed <= 0)
                {
                    _currentWalkingSpeed = session.LogicSettings.WalkingSpeedInKilometerPerHour;
                }
                if (session.LogicSettings.UseWalkingSpeedVariant)
                {
                    _currentWalkingSpeed = session.Navigation.VariantRandom(session, _currentWalkingSpeed);
                }

                var speedInMetersPerSecond = _currentWalkingSpeed / 3.6;
                var nextStepBearing        = LocationUtils.DegreeBearing(currentLocation, nextStep);
                //particular steps are limited by minimal length, first step is calculated from the original speed per second (distance in 1s)
                var nextStepDistance = Math.Max(RandomizeStepLength(_minStepLengthInMeters), speedInMetersPerSecond);
                Logger.Write($"Distance to walk in the next position update: {nextStepDistance.ToString("0.00")}m bearing: {nextStepBearing.ToString("0.00")}", LogLevel.Debug, force: true);

                var waypoint = LocationUtils.CreateWaypoint(currentLocation, nextStepDistance, nextStepBearing);
                walkedPointsList.Add(waypoint);

                var previousLocation    = currentLocation; //store the current location for comparison and correction purposes
                var requestSendDateTime = DateTime.Now;
                result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude);

                var realDistanceToTarget = LocationUtils.CalculateDistanceInMeters(currentLocation, targetLocation);
                Logger.Write($"Real remaining distance to target: {realDistanceToTarget.ToString("0.00")}m", LogLevel.Debug, force: true);
                if (realDistanceToTarget < 10)
                {
                    break;
                }

                do
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var msToPositionChange = (DateTime.Now - requestSendDateTime).TotalMilliseconds;
                    currentLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude);
                    var currentDistanceToWaypoint = LocationUtils.CalculateDistanceInMeters(currentLocation, nextStep);
                    realDistanceToTarget = LocationUtils.CalculateDistanceInMeters(currentLocation, targetLocation);
                    Logger.Write($"Actual position: {{lat: {currentLocation.Latitude}, lng: {currentLocation.Longitude}}}, reached in {msToPositionChange.ToString("0.00")}ms, distance from the next waypoint: {currentDistanceToWaypoint.ToString("0.000")}m, distance from the target: {realDistanceToTarget.ToString("0.000")}m", LogLevel.Debug, force: true);

                    var realSpeedinMperS   = nextStepDistance / (msToPositionChange / 1000);
                    var realDistanceWalked = LocationUtils.CalculateDistanceInMeters(previousLocation, currentLocation);
                    //if the real calculated speed is lower than the one expected, we will raise the speed for the following step
                    double speedRaise = 0;
                    if (realSpeedinMperS < speedInMetersPerSecond)
                    {
                        speedRaise = speedInMetersPerSecond - realSpeedinMperS;
                    }
                    double distanceRaise = 0;
                    if (realDistanceWalked < nextStepDistance)
                    {
                        distanceRaise = nextStepDistance - realDistanceWalked;
                    }
                    Logger.Write($"Actual/Expected speed: {realSpeedinMperS.ToString("0.00")}/{speedInMetersPerSecond.ToString("0.00")}m/s, actual/expected distance: {realDistanceWalked.ToString("0.00")}/{nextStepDistance.ToString("0.00")}m, next speed and dist raise by {speedRaise.ToString("0.00")}m/s and {distanceRaise.ToString("0.00")}m", LogLevel.Debug, force: true);

                    var realDistanceToTargetSpeedDown = LocationUtils.CalculateDistanceInMeters(currentLocation, targetLocation);
                    if (realDistanceToTargetSpeedDown < 40)
                    {
                        if (speedInMetersPerSecond > SpeedDownTo)
                        {
                            speedInMetersPerSecond = SpeedDownTo;
                        }
                    }

                    if (session.LogicSettings.UseWalkingSpeedVariant)
                    {
                        _currentWalkingSpeed   = session.Navigation.VariantRandom(session, _currentWalkingSpeed);
                        speedInMetersPerSecond = _currentWalkingSpeed / 3.6;
                    }
                    speedInMetersPerSecond += speedRaise;

                    nextStepBearing = LocationUtils.DegreeBearing(currentLocation, nextStep);

                    //setting next step distance is limited by the target and the next waypoint distance (we don't want to miss them)
                    //also the minimal step length is used as we don't want to spend minutes jumping by cm lengths
                    nextStepDistance = Math.Min(Math.Min(realDistanceToTarget, currentDistanceToWaypoint),
                                                //also add the distance raise (bot overhead corrections) to the normal step length
                                                Math.Max(RandomizeStepLength(_minStepLengthInMeters) + distanceRaise, (msToPositionChange / 1000) * speedInMetersPerSecond) + distanceRaise);

                    // After a correct waypoint, get a random imprecise point in 5 meters around player - more realistic
                    //var impreciseLocation = GenerateUnaccurateGeocoordinate(waypoint, nextWaypointBearing);
                    Logger.Write($"Distance to walk in the next position update: {nextStepDistance.ToString("0.00")}, bearing: {nextStepBearing.ToString("0.00")}, speed: {speedInMetersPerSecond.ToString("0.00")}", LogLevel.Debug, force: true);

                    waypoint = LocationUtils.CreateWaypoint(currentLocation, nextStepDistance, nextStepBearing);
                    walkedPointsList.Add(waypoint);

                    previousLocation    = currentLocation; //store the current location for comparison and correction purposes
                    requestSendDateTime = DateTime.Now;
                    result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude);

                    UpdatePositionEvent?.Invoke(waypoint.Latitude, waypoint.Longitude);

                    if (functionExecutedWhileWalking != null)
                    {
                        await functionExecutedWhileWalking(); // look for pokemon
                    }
                } while (LocationUtils.CalculateDistanceInMeters(currentLocation, nextStep) >= 2);

                UpdatePositionEvent?.Invoke(nextStep.Latitude, nextStep.Longitude);
            }

            stringifiedPath = string.Join(",\n", walkedPointsList.Select(point => $"{{lat: {point.Latitude}, lng: {point.Longitude}}}"));
            session.EventDispatcher.Send(new PathEvent
            {
                IsCalculated    = false,
                StringifiedPath = stringifiedPath
            });

            return(result);
        }
        public async Task <PlayerUpdateResponse> Walk(GeoCoordinate targetLocation, Func <Task <bool> > functionExecutedWhileWalking, ISession session, CancellationToken cancellationToken)
        {
            GetGoogleInstance(session);
            var sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude, _client.CurrentAltitude);
            var googleResult   = _googleDirectionsService.GetDirections(sourceLocation, new List <GeoCoordinate>(), targetLocation);

            if (googleResult.Directions.status.Equals("OVER_QUERY_LIMIT"))
            {
                return(await RedirectToHumanStrategy(targetLocation, functionExecutedWhileWalking, session, cancellationToken));
            }
            session.EventDispatcher.Send(new NewPathToDestinyEvent {
                GoogleData = googleResult
            });

            var googleWalk = GoogleWalk.Get(googleResult);

            PlayerUpdateResponse result = null;
            List <GeoCoordinate> points = googleWalk.Waypoints;

            foreach (var nextStep in points)
            {
                var speedInMetersPerSecond = session.LogicSettings.UseWalkingSpeedVariant ? MajorWalkingSpeedVariant(session) :
                                             session.LogicSettings.WalkingSpeedInKilometerPerHour / 3.6;
                sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude);

                var nextWaypointBearing  = LocationUtils.DegreeBearing(sourceLocation, nextStep);
                var nextWaypointDistance = speedInMetersPerSecond;
                var waypoint             = LocationUtils.CreateWaypoint(sourceLocation, nextWaypointDistance, nextWaypointBearing);

                var requestSendDateTime = DateTime.Now;
                result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude);

                UpdatePositionEvent?.Invoke(waypoint.Latitude, waypoint.Longitude);

                var realDistanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation);
                if (realDistanceToTarget < 10)
                {
                    break;
                }

                do
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var millisecondsUntilGetUpdatePlayerLocationResponse = (DateTime.Now - requestSendDateTime).TotalMilliseconds;

                    sourceLocation = new GeoCoordinate(_client.CurrentLatitude, _client.CurrentLongitude);
                    var currentDistanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, nextStep);

                    var realDistanceToTargetSpeedDown = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation);
                    if (realDistanceToTargetSpeedDown < 40)
                    {
                        if (speedInMetersPerSecond > SpeedDownTo)
                        {
                            speedInMetersPerSecond = SpeedDownTo;
                        }
                    }

                    if (session.LogicSettings.UseWalkingSpeedVariant)
                    {
                        speedInMetersPerSecond = MinorWalkingSpeedVariant(session);
                    }

                    nextWaypointDistance = Math.Min(currentDistanceToTarget, millisecondsUntilGetUpdatePlayerLocationResponse / 1000 * speedInMetersPerSecond);
                    nextWaypointBearing  = LocationUtils.DegreeBearing(sourceLocation, nextStep);
                    waypoint             = LocationUtils.CreateWaypoint(sourceLocation, nextWaypointDistance, nextWaypointBearing);

                    requestSendDateTime = DateTime.Now;
                    result = await _client.Player.UpdatePlayerLocation(waypoint.Latitude, waypoint.Longitude, waypoint.Altitude);

                    UpdatePositionEvent?.Invoke(waypoint.Latitude, waypoint.Longitude);

                    if (functionExecutedWhileWalking != null)
                    {
                        await functionExecutedWhileWalking(); // look for pokemon
                    }
                } while (LocationUtils.CalculateDistanceInMeters(sourceLocation, nextStep) >= 2);

                UpdatePositionEvent?.Invoke(nextStep.Latitude, nextStep.Longitude);
            }

            return(result);
        }