Example #1
0
        public static void Test(FileInfo screenshotInfo)
        {
            Bitmap bitmap;

            try
            {
                Image image = Image.FromFile(screenshotInfo.FullName);
                bitmap = new Bitmap(image);
            }
            catch (Exception e)
            {
                throw new IOException("Invalid screenshot file", e);
            }

            int[] pixels = new int[bitmap.Width * bitmap.Height];

            BitmapData bitmapData = bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);

            Marshal.Copy(bitmapData.Scan0, pixels, 0, pixels.Length);
            bitmap.UnlockBits(bitmapData);

            Task <ImageData> processTask = ImageProcessor.Process(pixels, bitmap.Width, bitmap.Height);

            processTask.Wait();

            ImageData data = processTask.Result;

            // Detect player level
            int?playerLevel = Program.PlayerLevel;

            Match directoryNameMatch = Program.DirectoryNameRegex.Match(screenshotInfo.Directory.Name);

            if (directoryNameMatch.Success)
            {
                playerLevel = int.Parse(directoryNameMatch.Groups["Level"].Value);
            }

            if (playerLevel == null)
            {
                throw new Exception("Could not detect player level. Please specify default player level parameter.");
            }

            // Compute pokemon level
            double pokemonLevel = PokemonInfo.GetPokemonLevel(playerLevel.Value, data.LevelAngle);

            // Find matching pokemon
            if (Program.OnlyCandy)
            {
                data.Name = "Toto";
            }

            PokemonInfo candyPokemon = string.IsNullOrEmpty(data.Candy) ? null : Constants.Pokemons.MinValue(p =>
            {
                int englishDiff = p.EnglishName != null ? Utilities.Diff(data.Candy, p.EnglishName) : int.MaxValue;
                int frenchDiff  = p.FrenchName != null ? Utilities.Diff(data.Candy, p.FrenchName) : int.MaxValue;
                int germanDiff  = p.GermanName != null ? Utilities.Diff(data.Candy, p.GermanName) : int.MaxValue;

                return(Math.Min(Math.Min(englishDiff, frenchDiff), germanDiff));
            });
            PokemonInfo pokemon = Constants.Pokemons.MinValue(p =>
            {
                float nameRatio = 1;

                Func <string, string> normalize = v => v.Replace("i", "l");

                if (data.Name != null)
                {
                    int englishDiff = p.EnglishName != null ? Utilities.Diff(normalize(data.Name), normalize(p.EnglishName)) : int.MaxValue;
                    int frenchDiff  = p.FrenchName != null ? Utilities.Diff(normalize(data.Name), normalize(p.FrenchName)) : int.MaxValue;
                    int germanDiff  = p.GermanName != null ? Utilities.Diff(normalize(data.Name), normalize(p.GermanName)) : int.MaxValue;

                    nameRatio = Math.Min(Math.Min(englishDiff, frenchDiff), germanDiff);
                }

                float evolutionRatio = candyPokemon == null ? -1 : (p.Id - candyPokemon.Id) / 6f;
                if (evolutionRatio < 0 || evolutionRatio > 1)
                {
                    evolutionRatio = 2;
                }
                else if (evolutionRatio > 0.5f)
                {
                    evolutionRatio = 0.5f;
                }

                float cpRatio = data.CP >= p.GetMinimumCP(pokemonLevel) && data.CP <= p.GetMaximumCP(pokemonLevel) ? 0.25f : 1;
                float hpRatio = data.HP >= p.GetMinimumHP(pokemonLevel) && data.HP <= p.GetMaximumHP(pokemonLevel) ? 0.25f : 1;

                return(nameRatio * (evolutionRatio + 0.1f) * cpRatio * hpRatio);
            });

            // Simulate IV possibilities
            Tuple <int, int, int>[] ivPossibilities = Enumerable.Range(0, 16).SelectMany(atk => Enumerable.Range(0, 16).SelectMany(def => Enumerable.Range(0, 16).Select(sta => Tuple.Create(atk, def, sta)))).ToArray();
            Tuple <int, int, int>[] matchingIVs     = ivPossibilities.AsParallel().Where(ivPossibility =>
            {
                int cp = (int)(((pokemon.BaseAttack + ivPossibility.Item1) * Math.Sqrt(pokemon.BaseDefense + ivPossibility.Item2) * Math.Sqrt(pokemon.BaseStamina + ivPossibility.Item3) * Math.Pow(Constants.CPMultipliers[pokemonLevel], 2)) / 10);
                int hp = (int)((pokemon.BaseStamina + ivPossibility.Item3) * Constants.CPMultipliers[pokemonLevel]);

                return(data.CP == cp && data.HP == hp);
            }).ToArray();

            string displayName = pokemon.EnglishName.Replace("♀", "F").Replace("♂", "M");

            Console.WriteLine($"{screenshotInfo.Name} > {{ Name: {data.Name}, Lvl: {pokemonLevel}, CP: {data.CP}, HP: {data.HP}, Pokemon: {displayName} }}");

            // Validate against file name
            Match screenshotNameMatch = Program.ScreenshotNameRegex.Match(screenshotInfo.Name);

            if (screenshotNameMatch.Success)
            {
                // Decode file name
                string validationName = screenshotNameMatch.Groups["Name"].Value;

                string validationLevelString = screenshotNameMatch.Groups["Level"].Value;
                double?validationLevel       = null;
                if (validationLevelString.ToLower() != "x")
                {
                    validationLevel = double.Parse(validationLevelString);
                }

                int validationHp = int.Parse(screenshotNameMatch.Groups["Hp"].Value);
                int validationCp = int.Parse(screenshotNameMatch.Groups["Cp"].Value);

                // Validate data
                Assert.True(validationName.Trim().ToLower() == displayName.Trim().ToLower(), $"Detected name is \"{displayName}\". Should be \"{validationName}\"");
                Assert.True(validationCp == data.CP, $"Detected CP is {data.CP}. Should be {validationCp}");
                Assert.True(validationHp == data.HP, $"Detected HP is {data.HP}. Should be {validationHp}");

                if (validationLevel != null)
                {
                    Assert.True(validationLevel == pokemonLevel, $"Detected level is {pokemonLevel}. Should be {validationLevel} (arc angle is {data.LevelAngle})");
                }
            }
        }