diff --git a/PokemonGo.RocketAPI.Logic/Inventory.cs b/PokemonGo.RocketAPI.Logic/Inventory.cs index 9e9ff5cf4..94cc06fed 100644 --- a/PokemonGo.RocketAPI.Logic/Inventory.cs +++ b/PokemonGo.RocketAPI.Logic/Inventory.cs @@ -5,6 +5,9 @@ using System.Threading.Tasks; using PokemonGo.RocketAPI.Enums; using PokemonGo.RocketAPI.GeneratedCode; +using System.Collections.Concurrent; +using System; +using System.Threading; #endregion @@ -13,6 +16,8 @@ namespace PokemonGo.RocketAPI.Logic public class Inventory { private readonly Client _client; + private DateTime _lastRefresh; + private GetInventoryResponse _cachedInventory; public Inventory(Client client) { @@ -48,7 +53,7 @@ public async Task> GetDuplicatePokemonToTransfer( if (settings.CandyToEvolve == 0) continue; - var amountToSkip = familyCandy.Candy/settings.CandyToEvolve; + var amountToSkip = familyCandy.Candy / settings.CandyToEvolve; results.AddRange(pokemonList.Where(x => x.PokemonId == pokemon.Key && x.Favorite == 0) .OrderByDescending(x => x.Cp) @@ -98,12 +103,12 @@ public async Task GetHighestPokemonOfTypeByCP(PokemonData pokemon) public async Task GetItemAmountByType(MiscEnums.Item type) { var pokeballs = await GetItems(); - return pokeballs.FirstOrDefault(i => (MiscEnums.Item) i.Item_ == type)?.Count ?? 0; + return pokeballs.FirstOrDefault(i => (MiscEnums.Item)i.Item_ == type)?.Count ?? 0; } public async Task> GetItems() { - var inventory = await _client.GetInventory(); + var inventory = await getCachedInventory(); return inventory.InventoryDelta.InventoryItems .Select(i => i.InventoryItemData?.Item) .Where(p => p != null); @@ -114,20 +119,20 @@ public async Task> GetItemsToRecycle(ISettings settings) var myItems = await GetItems(); return myItems - .Where(x => settings.ItemRecycleFilter.Any(f => f.Key == (ItemId) x.Item_ && x.Count > f.Value)) + .Where(x => settings.ItemRecycleFilter.Any(f => f.Key == (ItemId)x.Item_ && x.Count > f.Value)) .Select( x => new Item { Item_ = x.Item_, - Count = x.Count - settings.ItemRecycleFilter.Single(f => f.Key == (ItemId) x.Item_).Value, + Count = x.Count - settings.ItemRecycleFilter.Single(f => f.Key == (ItemId)x.Item_).Value, Unseen = x.Unseen }); } public async Task> GetPlayerStats() { - var inventory = await _client.GetInventory(); + var inventory = await getCachedInventory(); return inventory.InventoryDelta.InventoryItems .Select(i => i.InventoryItemData?.PlayerStats) .Where(p => p != null); @@ -135,7 +140,7 @@ public async Task> GetPlayerStats() public async Task> GetPokemonFamilies() { - var inventory = await _client.GetInventory(); + var inventory = await getCachedInventory(); return inventory.InventoryDelta.InventoryItems.Select(i => i.InventoryItemData?.PokemonFamily) .Where(p => p != null && p.FamilyId != PokemonFamilyId.FamilyUnset); @@ -143,7 +148,7 @@ public async Task> GetPokemonFamilies() public async Task> GetPokemons() { - var inventory = await _client.GetInventory(); + var inventory = await getCachedInventory(); return inventory.InventoryDelta.InventoryItems.Select(i => i.InventoryItemData?.Pokemon) .Where(p => p != null && p.PokemonId > 0); @@ -186,7 +191,7 @@ public async Task> GetPokemonToEvolve(IEnumerable pokemonSettings.Single(x => x.PokemonId == p.PokemonId).FamilyId == settings.FamilyId)* + p => pokemonSettings.Single(x => x.PokemonId == p.PokemonId).FamilyId == settings.FamilyId) * settings.CandyToEvolve; if (familyCandy.Candy - pokemonCandyNeededAlready > settings.CandyToEvolve) pokemonToEvolve.Add(pokemon); @@ -194,5 +199,32 @@ public async Task> GetPokemonToEvolve(IEnumerable getCachedInventory() + { + var now = DateTime.UtcNow; + SemaphoreSlim ss = new SemaphoreSlim(10); + + if (_lastRefresh != null && _lastRefresh.AddSeconds(30).Ticks > now.Ticks) + { + return _cachedInventory; + } + else + { + await ss.WaitAsync(); + try + { + _lastRefresh = now; + _cachedInventory = await _client.GetInventory(); + return _cachedInventory; + } + finally + { + ss.Release(); + } + } + + } } } \ No newline at end of file diff --git a/PokemonGo.RocketAPI.Logic/Logic.cs b/PokemonGo.RocketAPI.Logic/Logic.cs index 5ca455c11..1f4fdbe36 100644 --- a/PokemonGo.RocketAPI.Logic/Logic.cs +++ b/PokemonGo.RocketAPI.Logic/Logic.cs @@ -11,6 +11,7 @@ using PokemonGo.RocketAPI.GeneratedCode; using PokemonGo.RocketAPI.Helpers; using PokemonGo.RocketAPI.Logic.Utils; +using System.Device.Location; #endregion @@ -52,7 +53,7 @@ private async Task CatchEncounter(EncounterResponse encounter, MapPokemon pokemo } var pokeball = await GetBestBall(encounter?.WildPokemon); - var distance = Navigation.DistanceBetween2Coordinates(_client.CurrentLat, _client.CurrentLng, + var distance = LocationUtils.CalculateDistanceInMeters(_client.CurrentLat, _client.CurrentLng, pokemon.Latitude, pokemon.Longitude); caughtPokemonResponse = await @@ -272,9 +273,7 @@ private async Task ExecuteCatchAllNearbyPokemons() mapObjects.MapCells.SelectMany(i => i.CatchablePokemons) .OrderBy( i => - LocationUtils.CalculateDistanceInMeters( - new Navigation.Location(_client.CurrentLat, _client.CurrentLng), - new Navigation.Location(i.Latitude, i.Longitude))); + LocationUtils.CalculateDistanceInMeters(_client.CurrentLat, _client.CurrentLng,i.Latitude, i.Longitude)); foreach (var pokemon in pokemons) { @@ -286,7 +285,7 @@ private async Task ExecuteCatchAllNearbyPokemons() continue; } - var distance = Navigation.DistanceBetween2Coordinates(_client.CurrentLat, _client.CurrentLng, + var distance = LocationUtils.CalculateDistanceInMeters(_client.CurrentLat, _client.CurrentLng, pokemon.Latitude, pokemon.Longitude); await Task.Delay(distance > 100 ? 15000 : 500); @@ -314,18 +313,16 @@ private async Task ExecuteFarmingPokestopsAndPokemons() i.CooldownCompleteTimestampMs < DateTime.UtcNow.ToUnixTime()) .OrderBy( i => - LocationUtils.CalculateDistanceInMeters( - new Navigation.Location(_client.CurrentLat, _client.CurrentLng), - new Navigation.Location(i.Latitude, i.Longitude))); + LocationUtils.CalculateDistanceInMeters(_client.CurrentLat, _client.CurrentLng,i.Latitude, i.Longitude)); foreach (var pokeStop in pokeStops) { - var distance = Navigation.DistanceBetween2Coordinates(_client.CurrentLat, _client.CurrentLng, + var distance = LocationUtils.CalculateDistanceInMeters(_client.CurrentLat, _client.CurrentLng, pokeStop.Latitude, pokeStop.Longitude); var update = await - _navigation.HumanLikeWalking(new Navigation.Location(pokeStop.Latitude, pokeStop.Longitude), + _navigation.HumanLikeWalking(new GeoCoordinate(pokeStop.Latitude, pokeStop.Longitude), _clientSettings.WalkingSpeedInKilometerPerHour, ExecuteCatchAllNearbyPokemons); var fortInfo = await _client.GetFort(pokeStop.Id, pokeStop.Latitude, pokeStop.Longitude); diff --git a/PokemonGo.RocketAPI.Logic/Navigation.cs b/PokemonGo.RocketAPI.Logic/Navigation.cs index 19b75cf6e..e19a81470 100644 --- a/PokemonGo.RocketAPI.Logic/Navigation.cs +++ b/PokemonGo.RocketAPI.Logic/Navigation.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using PokemonGo.RocketAPI.GeneratedCode; using PokemonGo.RocketAPI.Logic.Utils; +using System.Device.Location; #endregion @@ -19,24 +20,12 @@ public Navigation(Client client) _client = client; } - public static double DistanceBetween2Coordinates(double lat1, double lng1, double lat2, double lng2) - { - const double rEarth = 6378137; - var dLat = (lat2 - lat1)*Math.PI/180; - var dLon = (lng2 - lng1)*Math.PI/180; - var alpha = Math.Sin(dLat/2)*Math.Sin(dLat/2) - + Math.Cos(lat1*Math.PI/180)*Math.Cos(lat2*Math.PI/180) - *Math.Sin(dLon/2)*Math.Sin(dLon/2); - var d = 2*rEarth*Math.Atan2(Math.Sqrt(alpha), Math.Sqrt(1 - alpha)); - return d; - } - - public async Task HumanLikeWalking(Location targetLocation, + public async Task HumanLikeWalking(GeoCoordinate targetLocation, double walkingSpeedInKilometersPerHour, Func functionExecutedWhileWalking) { var speedInMetersPerSecond = walkingSpeedInKilometersPerHour/3.6; - var sourceLocation = new Location(_client.CurrentLat, _client.CurrentLng); + var sourceLocation = new GeoCoordinate(_client.CurrentLat, _client.CurrentLng); var distanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation); // Logger.Write($"Distance to target location: {distanceToTarget:0.##} meters. Will take {distanceToTarget/speedInMetersPerSecond:0.##} seconds!", LogLevel.Info); @@ -57,7 +46,7 @@ public async Task HumanLikeWalking(Location targetLocation var millisecondsUntilGetUpdatePlayerLocationResponse = (DateTime.Now - requestSendDateTime).TotalMilliseconds; - sourceLocation = new Location(_client.CurrentLat, _client.CurrentLng); + sourceLocation = new GeoCoordinate(_client.CurrentLat, _client.CurrentLng); var currentDistanceToTarget = LocationUtils.CalculateDistanceInMeters(sourceLocation, targetLocation); if (currentDistanceToTarget < 40) @@ -84,17 +73,5 @@ public async Task HumanLikeWalking(Location targetLocation return result; } - - public class Location - { - public Location(double latitude, double longitude) - { - Latitude = latitude; - Longitude = longitude; - } - - public double Latitude { get; set; } - public double Longitude { get; set; } - } } } \ No newline at end of file diff --git a/PokemonGo.RocketAPI.Logic/PokemonGo.RocketAPI.Logic.csproj b/PokemonGo.RocketAPI.Logic/PokemonGo.RocketAPI.Logic.csproj index 298232d1c..c9e56cfc2 100644 --- a/PokemonGo.RocketAPI.Logic/PokemonGo.RocketAPI.Logic.csproj +++ b/PokemonGo.RocketAPI.Logic/PokemonGo.RocketAPI.Logic.csproj @@ -36,6 +36,7 @@ + diff --git a/PokemonGo.RocketAPI.Logic/Utils/LocationUtils.cs b/PokemonGo.RocketAPI.Logic/Utils/LocationUtils.cs index c4ba896f1..8b6dc09be 100644 --- a/PokemonGo.RocketAPI.Logic/Utils/LocationUtils.cs +++ b/PokemonGo.RocketAPI.Logic/Utils/LocationUtils.cs @@ -1,6 +1,7 @@ #region using System; +using System.Device.Location; using static PokemonGo.RocketAPI.Logic.Navigation; #endregion @@ -9,26 +10,21 @@ namespace PokemonGo.RocketAPI.Logic.Utils { public static class LocationUtils { - public static double CalculateDistanceInMeters(Location sourceLocation, Location targetLocation) + public static double CalculateDistanceInMeters(double sourceLat, double sourceLng, double destLat, double destLng) // from http://stackoverflow.com/questions/6366408/calculating-distance-between-two-latitude-and-longitude-geocoordinates { - var baseRad = Math.PI*sourceLocation.Latitude/180; - var targetRad = Math.PI*targetLocation.Latitude/180; - var theta = sourceLocation.Longitude - targetLocation.Longitude; - var thetaRad = Math.PI*theta/180; + var sourceLocation = new GeoCoordinate(sourceLat, sourceLng); + var targetLocation = new GeoCoordinate(destLat, destLng); - var dist = - Math.Sin(baseRad)*Math.Sin(targetRad) + Math.Cos(baseRad)* - Math.Cos(targetRad)*Math.Cos(thetaRad); - dist = Math.Acos(dist); - - dist = dist*180/Math.PI; - dist = dist*60*1.1515*1.609344*1000; + return sourceLocation.GetDistanceTo(targetLocation); + } - return dist; + public static double CalculateDistanceInMeters(GeoCoordinate sourceLocation, GeoCoordinate destinationLocation) + { + return CalculateDistanceInMeters(sourceLocation.Latitude, sourceLocation.Longitude, destinationLocation.Latitude, destinationLocation.Longitude); } - public static Location CreateWaypoint(Location sourceLocation, double distanceInMeters, double bearingDegrees) + public static GeoCoordinate CreateWaypoint(GeoCoordinate sourceLocation, double distanceInMeters, double bearingDegrees) //from http://stackoverflow.com/a/17545955 { var distanceKm = distanceInMeters/1000.0; @@ -52,10 +48,10 @@ public static Location CreateWaypoint(Location sourceLocation, double distanceIn // adjust toLonRadians to be in the range -180 to +180... targetLongitudeRadians = (targetLongitudeRadians + 3*Math.PI)%(2*Math.PI) - Math.PI; - return new Location(ToDegrees(targetLatitudeRadians), ToDegrees(targetLongitudeRadians)); + return new GeoCoordinate(ToDegrees(targetLatitudeRadians), ToDegrees(targetLongitudeRadians)); } - public static double DegreeBearing(Location sourceLocation, Location targetLocation) + public static double DegreeBearing(GeoCoordinate sourceLocation, GeoCoordinate targetLocation) // from http://stackoverflow.com/questions/2042599/direction-between-2-latitude-longitude-points-in-c-sharp { var dLon = ToRad(targetLocation.Longitude - sourceLocation.Longitude);