diff --git a/PoGo.NecroBot.Logic/ILogicSettings.cs b/PoGo.NecroBot.Logic/ILogicSettings.cs index fd9252bf7..044c61efe 100644 --- a/PoGo.NecroBot.Logic/ILogicSettings.cs +++ b/PoGo.NecroBot.Logic/ILogicSettings.cs @@ -47,7 +47,7 @@ public TransferFilter() } public TransferFilter(int keepMinCp, int keepMinLvl, bool useKeepMinLvl, float keepMinIvPercentage, string keepMinOperator, int keepMinDuplicatePokemon, - List moves = null) + List moves = null, string movesOperator = "or") { KeepMinCp = keepMinCp; KeepMinLvl = keepMinLvl; @@ -56,6 +56,7 @@ public TransferFilter(int keepMinCp, int keepMinLvl, bool useKeepMinLvl, float k KeepMinDuplicatePokemon = keepMinDuplicatePokemon; KeepMinOperator = keepMinOperator; Moves = moves ?? new List(); + MovesOperator = movesOperator; } public int KeepMinCp { get; set; } @@ -65,6 +66,7 @@ public TransferFilter(int keepMinCp, int keepMinLvl, bool useKeepMinLvl, float k public int KeepMinDuplicatePokemon { get; set; } public List Moves { get; set; } public string KeepMinOperator { get; set; } + public string MovesOperator { get; set; } } public interface ILogicSettings diff --git a/PoGo.NecroBot.Logic/Inventory.cs b/PoGo.NecroBot.Logic/Inventory.cs index d3f750550..04f10da16 100644 --- a/PoGo.NecroBot.Logic/Inventory.cs +++ b/PoGo.NecroBot.Logic/Inventory.cs @@ -15,11 +15,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using PoGo.NecroBot.Logic.Utils; #endregion namespace PoGo.NecroBot.Logic { + public class Inventory { private readonly Client _client; @@ -82,6 +84,10 @@ private async Task GetCachedInventory() return await RefreshCachedInventory(); } + + + + public async Task> GetDuplicatePokemonToTransfer( IEnumerable pokemonsNotToTransfer, IEnumerable pokemonsToEvolve, bool keepPokemonsThatCanEvolve = false, bool prioritizeIVoverCp = false @@ -99,17 +105,15 @@ public async Task> GetDuplicatePokemonToTransfer( { var pokemonTransferFilter = GetPokemonTransferFilter(p.PokemonId); - return pokemonTransferFilter.KeepMinOperator.ToLower().Equals("and") - ? - (!((p.Cp >= pokemonTransferFilter.KeepMinCp && - PokemonInfo.CalculatePokemonPerfection(p) >= pokemonTransferFilter.KeepMinIvPercentage) || - pokemonTransferFilter.Moves.Intersect(new[] { p.Move1, p.Move2 }).Any() || - (PokemonInfo.GetLevel(p) >= pokemonTransferFilter.KeepMinLvl && pokemonTransferFilter.UseKeepMinLvl))) - : - !((p.Cp >= pokemonTransferFilter.KeepMinCp || - PokemonInfo.CalculatePokemonPerfection(p) >= pokemonTransferFilter.KeepMinIvPercentage) || - pokemonTransferFilter.Moves.Intersect(new[] { p.Move1, p.Move2 }).Any() || - (PokemonInfo.GetLevel(p) >= pokemonTransferFilter.KeepMinLvl && pokemonTransferFilter.UseKeepMinLvl)); + return + !pokemonTransferFilter.MovesOperator.BoolFunc( + pokemonTransferFilter.Moves.Intersect(new[] { p.Move1, p.Move2 }).Any(), + pokemonTransferFilter.KeepMinOperator.BoolFunc( + p.Cp >= pokemonTransferFilter.KeepMinCp, + PokemonInfo.CalculatePokemonPerfection(p) >= pokemonTransferFilter.KeepMinIvPercentage, + pokemonTransferFilter.KeepMinOperator.ReverseBoolFunc( + pokemonTransferFilter.KeepMinOperator.InverseBool(pokemonTransferFilter.UseKeepMinLvl), + PokemonInfo.GetLevel(p) >= pokemonTransferFilter.KeepMinLvl))); }).ToList(); @@ -137,8 +141,10 @@ public async Task> GetDuplicatePokemonToTransfer( settings.EvolutionIds.Count != 0) { var possibleCountToEvolve = familyCandy.Candy_ / settings.CandyToEvolve; - modFromEvolve = familyCandy.Candy_%settings.CandyToEvolve; amountToKeepInStorage = Math.Max(amountToKeepInStorage, possibleCountToEvolve); + + //remain candy + modFromEvolve = familyCandy.Candy_%settings.CandyToEvolve; } var inStorage = myPokemonList.Count(data => data.PokemonId == pokemonGroupToTransfer.Key); @@ -157,8 +163,11 @@ public async Task> GetDuplicatePokemonToTransfer( //Lets calc new canBeRemoved pokemons according to transferring some of them and use it as future candy to keepPokemonsThatCanEvolve if (modFromEvolve.HasValue) { - canBeRemoved = (settings.CandyToEvolve * canBeRemoved - modFromEvolve.Value) / (1 + settings.CandyToEvolve) + - Math.Sign(settings.CandyToEvolve * canBeRemoved - modFromEvolve.Value) % (1 + settings.CandyToEvolve); + // its an solution in fixed numbers of equations with two variables + // (N = X + Y, X + C >= Y * E) -> (X >= (N * E - C / 1 + E) + // where N - current canBeRemoved, X - new canBeRemoved, Y - possible to keep more, E - CandyToEvolve, C - modFromEvolve(remain candy) ) ) + canBeRemoved = (settings.CandyToEvolve * canBeRemoved - modFromEvolve.Value) / (1 + settings.CandyToEvolve) + + Math.Sign((settings.CandyToEvolve * canBeRemoved - modFromEvolve.Value) % (1 + settings.CandyToEvolve)); } var skipCount = weakPokemonCount - canBeRemoved; @@ -175,10 +184,31 @@ public async Task> GetDuplicatePokemonToTransfer( results.AddRange(pokemonGroupToTransfer .OrderByDescending(x => x.Cp) .ThenByDescending(PokemonInfo.CalculatePokemonPerfection) - .Skip(skipCount) - .ToList()); + .Skip(skipCount)); } } + + #region For testing + /* + results.ForEach(data => + { + var bestPokemonOfType = (_logicSettings.PrioritizeIvOverCp + ? myPokemonList.Where(x => x.PokemonId == data.PokemonId) + .OrderByDescending(x => x.Cp) + .FirstOrDefault() + : myPokemonList.Where(x => x.PokemonId == data.PokemonId) + .OrderByDescending(PokemonInfo.CalculatePokemonPerfection) + .FirstOrDefault()) ?? data; + + var perfection = PokemonInfo.CalculatePokemonPerfection(data); + var cp = data.Cp; + + var bestPerfection = PokemonInfo.CalculatePokemonPerfection(bestPokemonOfType); + var bestCp = bestPokemonOfType.Cp; + }); + */ + #endregion + return results; } diff --git a/PoGo.NecroBot.Logic/Settings.cs b/PoGo.NecroBot.Logic/Settings.cs index 2138f3b14..f5b4d47c2 100644 --- a/PoGo.NecroBot.Logic/Settings.cs +++ b/PoGo.NecroBot.Logic/Settings.cs @@ -584,6 +584,11 @@ public static GlobalSettings Load(string path) { filter.Value.Moves = new List(); } + foreach (var filter in settings.PokemonsTransferFilter.Where(x => x.Value.MovesOperator == null)) + { + filter.Value.MovesOperator = "or"; + } + } catch (JsonReaderException exception) { diff --git a/PoGo.NecroBot.Logic/Utils/StringUtils.cs b/PoGo.NecroBot.Logic/Utils/StringUtils.cs index b1581be50..845d06202 100644 --- a/PoGo.NecroBot.Logic/Utils/StringUtils.cs +++ b/PoGo.NecroBot.Logic/Utils/StringUtils.cs @@ -1,5 +1,6 @@ #region using directives +using System; using System.Collections.Generic; using System.Linq; using POGOProtos.Inventory.Item; @@ -23,5 +24,32 @@ public static string GetSummedFriendlyNameOfItemAwardList(IEnumerable .Select(y => $"{y.Amount} x {y.ItemName}") .Aggregate((a, b) => $"{a}, {b}"); } + + + private static readonly Func AndFunc = (x, y) => x && y; + private static readonly Func OrFunc = (x, y) => x || y; + private static readonly Func> GetBoolOperator = + myOperator => myOperator.ToLower().Equals("and") ? AndFunc : OrFunc; + + public static bool BoolFunc(this bool expr, bool expr2, string operatorStr) + { + return GetBoolOperator(operatorStr)(expr, expr2); + } + + public static bool BoolFunc(this string operatorStr, params bool[] expr) + { + return operatorStr.ToLower().Equals("and") ? expr.All(b => b) : expr.Any(b => b); + } + + public static bool ReverseBoolFunc(this string operatorStr, params bool[] expr) + { + return operatorStr.ToLower().Equals("and") ? expr.Any(b => b) : expr.All(b => b); + } + + public static bool InverseBool(this string operatorStr, bool expr) + { + return operatorStr.ToLower().Equals("and") ? !expr : expr; + } + } } \ No newline at end of file