Example #1
0
        public static void Testar(ISession session)
        {
            var googleDirectionsService = new DirectionsService(session);

            var googleResult = googleDirectionsService.GetDirections(new GeoCoordinate(40.780599, -73.968862), new List <GeoCoordinate>(), new GeoCoordinate(40.781939, -73.965123));
            var googleWalk   = GoogleWalk.Get(googleResult);

            var proximo = googleWalk.NextStep(new GeoCoordinate(40.780573, -73.968842));
        }
Example #2
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);
        }